1 // RUN: %check_clang_tidy %s bugprone-suspicious-memset-usage %t
2 
3 void *memset(void *, int, __SIZE_TYPE__);
4 
5 namespace std {
6   using ::memset;
7 }
8 
9 template <typename T>
mtempl(int * ptr)10 void mtempl(int *ptr) {
11   memset(ptr, '0', sizeof(T));
12 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: memset fill value is char '0', potentially mistaken for int 0 [bugprone-suspicious-memset-usage]
13 // CHECK-FIXES: memset(ptr, 0, sizeof(T));
14   memset(ptr, 256, sizeof(T));
15 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: memset fill value is out of unsigned character range, gets truncated [bugprone-suspicious-memset-usage]
16   memset(0, sizeof(T), 0);
17 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
18 // CHECK-FIXES: memset(0, 0, sizeof(T));
19   memset(0, sizeof(int), 0);
20 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
21 // CHECK-FIXES: memset(0, 0, sizeof(int));
22 }
23 
foo(int xsize,int ysize)24 void foo(int xsize, int ysize) {
25   int i[5] = {1, 2, 3, 4, 5};
26   char ca[3] = {'a', 'b', 'c'};
27   int *p = i;
28   int l = 5;
29   char z = '1';
30   char *c = &z;
31   int v = 0;
32 
33   memset(p, '0', l);
34 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: memset fill value is char '0', potentially mistaken for int 0 [bugprone-suspicious-memset-usage]
35 // CHECK-FIXES: memset(p, 0, l);
36 
37   memset(p, 0xabcd, l);
38 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: memset fill value is out of unsigned character range, gets truncated [bugprone-suspicious-memset-usage]
39 
40   memset(p, sizeof(int), 0);
41 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
42 // CHECK-FIXES: memset(p, 0, sizeof(int));
43   std::memset(p, sizeof(int), 0x00);
44 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
45 // CHECK-FIXES: std::memset(p, 0x00, sizeof(int));
46 
47 #define M_CHAR_ZERO memset(p, '0', l);
48   M_CHAR_ZERO
49 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset fill value is char '0', potentially mistaken for int 0 [bugprone-suspicious-memset-usage]
50 
51 #define M_OUTSIDE_RANGE memset(p, 0xabcd, l);
52   M_OUTSIDE_RANGE
53 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset fill value is out of unsigned character range, gets truncated [bugprone-suspicious-memset-usage]
54 
55 #define M_ZERO_LENGTH memset(p, sizeof(int), 0);
56   M_ZERO_LENGTH
57 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: memset of size zero, potentially swapped arguments [bugprone-suspicious-memset-usage]
58 
59   memset(p, '2', l);
60   memset(p, 0, l);
61   memset(c, '0', 1);
62   memset(ca, '0', sizeof(ca));
63 
64   memset(p, 0x00, l);
65   mtempl<int>(p);
66 
67   memset(p, sizeof(int), v + 1);
68   memset(p, 0xcd, 1);
69 
70   // Don't warn when the fill char and the length are both known to be
71   // zero.  No bug is possible.
72   memset(p, 0, v);
73 
74   // -1 is clearly not a length by virtue of being negative, so no warning
75   // despite v == 0.
76   memset(p, -1, v);
77 }
78 
79 void *memset(int);
NoCrash()80 void NoCrash() {
81   memset(1);
82 }
83