1// RUN: %check_clang_tidy %s bugprone-sizeof-expression %t
2
3#define offsetof(type, member) __builtin_offsetof(type, member)
4
5typedef __SIZE_TYPE__ size_t;
6typedef __WCHAR_TYPE__ wchar_t;
7
8extern void *memset(void *Dest, int Ch, size_t Count);
9extern size_t strlen(const char *Str);
10extern size_t wcslen(const wchar_t *Str);
11extern char *strcpy(char *Dest, const char *Src);
12extern wchar_t *wcscpy(wchar_t *Dest, const wchar_t *Src);
13extern int scanf(const char *Format, ...);
14extern int wscanf(const wchar_t *Format, ...);
15
16extern void sink(const void *P);
17
18enum { BufferSize = 1024 };
19
20void 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
32void 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
45void 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
55void 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
66void good2(void) {
67 int Buffer[BufferSize];
68 int *P = Buffer;
69
70 while (P < Buffer + BufferSize) {
71 *P++ = 0;
72 }
73}
74
75struct S {
76 long A, B, C;
77};
78
79void 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(Dest: P + Offset, Ch: 0, Count: sizeof(struct S) - Offset);
86}
87
88void 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(Dest: P + Offset, Ch: 0, Count: sizeof(struct S) - Offset);
95}
96
97void bad3b(struct S *S) {
98 memset(Dest: S + offsetof(struct S, B), Ch: 0,
99 Count: 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
104void good3b(struct S *S) {
105 char *P = (char*)S;
106 memset(Dest: P + offsetof(struct S, B), Ch: 0,
107 Count: sizeof(struct S) - offsetof(struct S, B));
108}
109
110void 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(P: Q++);
119 }
120}
121
122void 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
135void 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
146void 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
157void 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
168void 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
179void 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
190void 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
201void 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
214void 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
225void 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
236void silenced7(void) {
237 char Buffer[BufferSize];
238
239 char *P = &Buffer[0];
240 const char *Q = P;
241 while (Q < P + BufferSize) {
242 sink(P: Q);
243 Q = Q + sizeof(*Q);
244 }
245}
246
247void good7(void) {
248 char Buffer[BufferSize];
249
250 char *P = &Buffer[0];
251 const char *Q = P;
252 while (Q < P + BufferSize) {
253 sink(P: Q);
254 Q = Q + 1;
255 }
256}
257
258void 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
271void 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
282void 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
293void 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
305void 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(P: &I);
313}
314
315void 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(P: &I);
323}
324
325void bad12(void) {
326 wchar_t Message[BufferSize];
327 wcscpy(Dest: Message, Src: L"Message: ");
328 wscanf(Format: L"%s", Message + wcslen(Str: 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
333void silenced12(void) {
334 char Message[BufferSize];
335 strcpy(Dest: Message, Src: "Message: ");
336 scanf(Format: "%s", Message + strlen(Str: Message) * sizeof(char));
337}
338
339void nomatch12(void) {
340 char Message[BufferSize];
341 strcpy(Dest: Message, Src: "Message: ");
342 scanf(Format: "%s", Message + strlen(Str: Message));
343}
344
345void good12(void) {
346 wchar_t Message[BufferSize];
347 wcscpy(Dest: Message, Src: L"Message: ");
348 wscanf(Format: L"%s", Message + wcslen(Str: Message));
349}
350
351void 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
374void 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

source code of clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression-pointer-arithmetics.c