382 lines · c
1// RUN: %check_clang_tidy %s bugprone-sizeof-expression %t2 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 '+' operator40 // 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 '+' operator61 // 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 is84 // not a direct child of the pointer arithmetics.85 memset(P + Offset, 0, 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 is93 // not a direct child of the pointer arithmetics.94 memset(P + Offset, 0, sizeof(struct S) - Offset);95}96 97void 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 '+' operator101 // 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(P + offsetof(struct S, B), 0,107 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 '+' operator117 // CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' in pointer arithmetic internally scales with 'sizeof(struct S)' == {{[0-9]+}}118 sink(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 '+=' operator131 // 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 '+' operator210 // 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(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(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 '-' operator267 // 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(&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(&I);323}324 325void 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 '+' operator330 // 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(Message, "Message: ");336 scanf("%s", Message + strlen(Message) * sizeof(char));337}338 339void nomatch12(void) {340 char Message[BufferSize];341 strcpy(Message, "Message: ");342 scanf("%s", Message + strlen(Message));343}344 345void good12(void) {346 wchar_t Message[BufferSize];347 wcscpy(Message, L"Message: ");348 wscanf(L"%s", Message + wcslen(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 is357 // 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 is363 // 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 is369 // 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 '+' operator378 // CHECK-MESSAGES: :[[@LINE-2]]:21: note: '+' in pointer arithmetic internally scales with 'sizeof(int)' == {{[0-9]+}}379 ++P;380 }381}382