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