1 // RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 %s -verify
2 // RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_PASS_OBJECT_SIZE
3 // RUN: %clang_cc1 -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_BUILTINS
4 // RUN: %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify
5 // RUN: %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_PASS_OBJECT_SIZE
6 // RUN: %clang_cc1 -xc++ -triple x86_64-apple-macosx10.14.0 %s -verify -DUSE_BUILTINS
7 
8 typedef unsigned long size_t;
9 
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13 
14 extern int sprintf(char *str, const char *format, ...);
15 
16 #if defined(USE_PASS_OBJECT_SIZE)
17 void *memcpy(void *dst, const void *src, size_t c);
18 static void *memcpy(void *dst __attribute__((pass_object_size(1))), const void *src, size_t c) __attribute__((overloadable)) __asm__("merp");
memcpy(void * const dst,const void * src,size_t c)19 static void *memcpy(void *const dst __attribute__((pass_object_size(1))), const void *src, size_t c) __attribute__((overloadable)) {
20   return 0;
21 }
22 #elif defined(USE_BUILTINS)
23 #define memcpy(x,y,z) __builtin_memcpy(x,y,z)
24 #else
25 void *memcpy(void *dst, const void *src, size_t c);
26 #endif
27 
28 #ifdef __cplusplus
29 }
30 #endif
31 
call_memcpy()32 void call_memcpy() {
33   char dst[10];
34   char src[20];
35   memcpy(dst, src, 20); // expected-warning {{memcpy' will always overflow; destination buffer has size 10, but size argument is 20}}
36 
37   if (sizeof(dst) == sizeof(src))
38     memcpy(dst, src, 20); // no warning, unreachable
39 }
40 
call_memcpy_type()41 void call_memcpy_type() {
42   struct pair {
43     int first;
44     int second;
45   };
46   struct pair p;
47   char buf[20];
48   memcpy(&p.first, buf, 20);
49 #ifdef USE_PASS_OBJECT_SIZE
50   // Use the more strict checking mode on the pass_object_size attribute:
51   // expected-warning@-3 {{memcpy' will always overflow; destination buffer has size 4, but size argument is 20}}
52 #else
53   // Or just fallback to type 0:
54   // expected-warning@-6 {{memcpy' will always overflow; destination buffer has size 8, but size argument is 20}}
55 #endif
56 }
57 
call_strncat()58 void call_strncat() {
59   char s1[10], s2[20];
60   __builtin_strncat(s2, s1, 20);
61   __builtin_strncat(s1, s2, 20); // expected-warning {{'strncat' size argument is too large; destination buffer has size 10, but size argument is 20}}
62 }
63 
call_strncpy()64 void call_strncpy() {
65   char s1[10], s2[20];
66   __builtin_strncpy(s2, s1, 20);
67   __builtin_strncpy(s1, s2, 20); // expected-warning {{'strncpy' size argument is too large; destination buffer has size 10, but size argument is 20}}
68 }
69 
call_stpncpy()70 void call_stpncpy() {
71   char s1[10], s2[20];
72   __builtin_stpncpy(s2, s1, 20);
73   __builtin_stpncpy(s1, s2, 20); // expected-warning {{'stpncpy' size argument is too large; destination buffer has size 10, but size argument is 20}}
74 }
75 
call_memmove()76 void call_memmove() {
77   char s1[10], s2[20];
78   __builtin_memmove(s2, s1, 20);
79   __builtin_memmove(s1, s2, 20); // expected-warning {{'memmove' will always overflow; destination buffer has size 10, but size argument is 20}}
80 }
81 
call_memset()82 void call_memset() {
83   char buf[10];
84   __builtin_memset(buf, 0xff, 10);
85   __builtin_memset(buf, 0xff, 11); // expected-warning {{'memset' will always overflow; destination buffer has size 10, but size argument is 11}}
86 }
87 
call_snprintf()88 void call_snprintf() {
89   char buf[10];
90   __builtin_snprintf(buf, 10, "merp");
91   __builtin_snprintf(buf, 11, "merp"); // expected-warning {{'snprintf' size argument is too large; destination buffer has size 10, but size argument is 11}}
92 }
93 
call_vsnprintf()94 void call_vsnprintf() {
95   char buf[10];
96   __builtin_va_list list;
97   __builtin_vsnprintf(buf, 10, "merp", list);
98   __builtin_vsnprintf(buf, 11, "merp", list); // expected-warning {{'vsnprintf' size argument is too large; destination buffer has size 10, but size argument is 11}}
99 }
100 
call_sprintf_chk(char * buf)101 void call_sprintf_chk(char *buf) {
102   __builtin___sprintf_chk(buf, 1, 6, "hell\n");
103   __builtin___sprintf_chk(buf, 1, 5, "hell\n");     // expected-warning {{'sprintf' will always overflow; destination buffer has size 5, but format string expands to at least 6}}
104   __builtin___sprintf_chk(buf, 1, 6, "hell\0 boy"); // expected-warning {{format string contains '\0' within the string body}}
105   __builtin___sprintf_chk(buf, 1, 2, "hell\0 boy"); // expected-warning {{format string contains '\0' within the string body}}
106   // expected-warning@-1 {{'sprintf' will always overflow; destination buffer has size 2, but format string expands to at least 5}}
107   __builtin___sprintf_chk(buf, 1, 6, "hello");
108   __builtin___sprintf_chk(buf, 1, 5, "hello"); // expected-warning {{'sprintf' will always overflow; destination buffer has size 5, but format string expands to at least 6}}
109   __builtin___sprintf_chk(buf, 1, 2, "%c", '9');
110   __builtin___sprintf_chk(buf, 1, 1, "%c", '9'); // expected-warning {{'sprintf' will always overflow; destination buffer has size 1, but format string expands to at least 2}}
111   __builtin___sprintf_chk(buf, 1, 2, "%d", 9);
112   __builtin___sprintf_chk(buf, 1, 1, "%d", 9); // expected-warning {{'sprintf' will always overflow; destination buffer has size 1, but format string expands to at least 2}}
113   __builtin___sprintf_chk(buf, 1, 2, "%i", 9);
114   __builtin___sprintf_chk(buf, 1, 1, "%i", 9); // expected-warning {{'sprintf' will always overflow; destination buffer has size 1, but format string expands to at least 2}}
115   __builtin___sprintf_chk(buf, 1, 2, "%o", 9);
116   __builtin___sprintf_chk(buf, 1, 1, "%o", 9); // expected-warning {{'sprintf' will always overflow; destination buffer has size 1, but format string expands to at least 2}}
117   __builtin___sprintf_chk(buf, 1, 2, "%u", 9);
118   __builtin___sprintf_chk(buf, 1, 1, "%u", 9); // expected-warning {{'sprintf' will always overflow; destination buffer has size 1, but format string expands to at least 2}}
119   __builtin___sprintf_chk(buf, 1, 2, "%x", 9);
120   __builtin___sprintf_chk(buf, 1, 1, "%x", 9); // expected-warning {{'sprintf' will always overflow; destination buffer has size 1, but format string expands to at least 2}}
121   __builtin___sprintf_chk(buf, 1, 2, "%X", 9);
122   __builtin___sprintf_chk(buf, 1, 1, "%X", 9); // expected-warning {{'sprintf' will always overflow; destination buffer has size 1, but format string expands to at least 2}}
123   __builtin___sprintf_chk(buf, 1, 2, "%hhd", (char)9);
124   __builtin___sprintf_chk(buf, 1, 1, "%hhd", (char)9); // expected-warning {{'sprintf' will always overflow; destination buffer has size 1, but format string expands to at least 2}}
125   __builtin___sprintf_chk(buf, 1, 2, "%hd", (short)9);
126   __builtin___sprintf_chk(buf, 1, 1, "%hd", (short)9); // expected-warning {{'sprintf' will always overflow; destination buffer has size 1, but format string expands to at least 2}}
127   __builtin___sprintf_chk(buf, 1, 2, "%ld", 9l);
128   __builtin___sprintf_chk(buf, 1, 1, "%ld", 9l); // expected-warning {{'sprintf' will always overflow; destination buffer has size 1, but format string expands to at least 2}}
129   __builtin___sprintf_chk(buf, 1, 2, "%lld", 9ll);
130   __builtin___sprintf_chk(buf, 1, 1, "%lld", 9ll); // expected-warning {{'sprintf' will always overflow; destination buffer has size 1, but format string expands to at least 2}}
131   __builtin___sprintf_chk(buf, 1, 2, "%%");
132   __builtin___sprintf_chk(buf, 1, 1, "%%"); // expected-warning {{'sprintf' will always overflow; destination buffer has size 1, but format string expands to at least 2}}
133   __builtin___sprintf_chk(buf, 1, 4, "%#x", 9);
134   __builtin___sprintf_chk(buf, 1, 3, "%#x", 9); // expected-warning {{'sprintf' will always overflow; destination buffer has size 3, but format string expands to at least 4}}
135   __builtin___sprintf_chk(buf, 1, 4, "%p", (void *)9);
136   __builtin___sprintf_chk(buf, 1, 3, "%p", (void *)9); // expected-warning {{'sprintf' will always overflow; destination buffer has size 3, but format string expands to at least 4}}
137   __builtin___sprintf_chk(buf, 1, 3, "%+d", 9);
138   __builtin___sprintf_chk(buf, 1, 2, "%+d", 9); // expected-warning {{'sprintf' will always overflow; destination buffer has size 2, but format string expands to at least 3}}
139   __builtin___sprintf_chk(buf, 1, 3, "% i", 9);
140   __builtin___sprintf_chk(buf, 1, 2, "% i", 9); // expected-warning {{'sprintf' will always overflow; destination buffer has size 2, but format string expands to at least 3}}
141   __builtin___sprintf_chk(buf, 1, 6, "%5d", 9);
142   __builtin___sprintf_chk(buf, 1, 5, "%5d", 9); // expected-warning {{'sprintf' will always overflow; destination buffer has size 5, but format string expands to at least 6}}
143   __builtin___sprintf_chk(buf, 1, 9, "%f", 9.f);
144   __builtin___sprintf_chk(buf, 1, 8, "%f", 9.f); // expected-warning {{'sprintf' will always overflow; destination buffer has size 8, but format string expands to at least 9}}
145   __builtin___sprintf_chk(buf, 1, 9, "%Lf", (long double)9.);
146   __builtin___sprintf_chk(buf, 1, 8, "%Lf", (long double)9.); // expected-warning {{'sprintf' will always overflow; destination buffer has size 8, but format string expands to at least 9}}
147   __builtin___sprintf_chk(buf, 1, 10, "%+f", 9.f);
148   __builtin___sprintf_chk(buf, 1, 9, "%+f", 9.f); // expected-warning {{'sprintf' will always overflow; destination buffer has size 9, but format string expands to at least 10}}
149   __builtin___sprintf_chk(buf, 1, 12, "%e", 9.f);
150   __builtin___sprintf_chk(buf, 1, 11, "%e", 9.f); // expected-warning {{'sprintf' will always overflow; destination buffer has size 11, but format string expands to at least 12}}
151 }
152 
call_sprintf()153 void call_sprintf() {
154   char buf[6];
155   sprintf(buf, "hell\0 boy"); // expected-warning {{format string contains '\0' within the string body}}
156   sprintf(buf, "hello b\0y"); // expected-warning {{format string contains '\0' within the string body}}
157   // expected-warning@-1 {{'sprintf' will always overflow; destination buffer has size 6, but format string expands to at least 8}}
158   sprintf(buf, "hello");
159   sprintf(buf, "hello!"); // expected-warning {{'sprintf' will always overflow; destination buffer has size 6, but format string expands to at least 7}}
160   sprintf(buf, "1234%%");
161   sprintf(buf, "12345%%"); // expected-warning {{'sprintf' will always overflow; destination buffer has size 6, but format string expands to at least 7}}
162   sprintf(buf, "1234%c", '9');
163   sprintf(buf, "12345%c", '9'); // expected-warning {{'sprintf' will always overflow; destination buffer has size 6, but format string expands to at least 7}}
164   sprintf(buf, "1234%d", 9);
165   sprintf(buf, "12345%d", 9); // expected-warning {{'sprintf' will always overflow; destination buffer has size 6, but format string expands to at least 7}}
166   sprintf(buf, "1234%lld", 9ll);
167   sprintf(buf, "12345%lld", 9ll); // expected-warning {{'sprintf' will always overflow; destination buffer has size 6, but format string expands to at least 7}}
168   sprintf(buf, "12%#x", 9);
169   sprintf(buf, "123%#x", 9); // expected-warning {{'sprintf' will always overflow; destination buffer has size 6, but format string expands to at least 7}}
170   sprintf(buf, "12%p", (void *)9);
171   sprintf(buf, "123%p", (void *)9); // expected-warning {{'sprintf' will always overflow; destination buffer has size 6, but format string expands to at least 7}}
172   sprintf(buf, "123%+d", 9);
173   sprintf(buf, "1234%+d", 9); // expected-warning {{'sprintf' will always overflow; destination buffer has size 6, but format string expands to at least 7}}
174   sprintf(buf, "123% i", 9);
175   sprintf(buf, "1234% i", 9); // expected-warning {{'sprintf' will always overflow; destination buffer has size 6, but format string expands to at least 7}}
176   sprintf(buf, "%5d", 9);
177   sprintf(buf, "1%5d", 9); // expected-warning {{'sprintf' will always overflow; destination buffer has size 6, but format string expands to at least 7}}
178   sprintf(buf, "%.3f", 9.f);
179   sprintf(buf, "5%.3f", 9.f); // expected-warning {{'sprintf' will always overflow; destination buffer has size 6, but format string expands to at least 7}}
180   sprintf(buf, "%+.2f", 9.f);
181   sprintf(buf, "%+.3f", 9.f); // expected-warning {{'sprintf' will always overflow; destination buffer has size 6, but format string expands to at least 7}}
182   sprintf(buf, "%.0e", 9.f);
183   sprintf(buf, "5%.1e", 9.f); // expected-warning {{'sprintf' will always overflow; destination buffer has size 6, but format string expands to at least 8}}
184 }
185 
186 #ifdef __cplusplus
187 template <class> struct S {
mfS188   void mf() const {
189     __builtin_memset(const_cast<char *>(mv), 0, 0);
190   }
191 
192   char mv[10];
193 };
194 
195 template <int A, int B>
call_memcpy_dep()196 void call_memcpy_dep() {
197   char bufferA[A];
198   char bufferB[B];
199   memcpy(bufferA, bufferB, 10); // expected-warning{{'memcpy' will always overflow; destination buffer has size 9, but size argument is 10}}
200 }
201 
call_call_memcpy()202 void call_call_memcpy() {
203   call_memcpy_dep<10, 9>();
204   call_memcpy_dep<9, 10>(); // expected-note {{in instantiation of function template specialization 'call_memcpy_dep<9, 10>' requested here}}
205 }
206 #endif
207