blob: d9c21c08421f7c7400b3e74f225b9659b108c1a8 [file] [log] [blame]
Erik Pilkingtonb6e16ea2019-03-18 19:23:45 +00001// 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
Erik Pilkington233ff942019-03-29 19:53:41 +00004// 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
Erik Pilkingtonb6e16ea2019-03-18 19:23:45 +00007
8typedef unsigned long size_t;
9
Erik Pilkington233ff942019-03-29 19:53:41 +000010#ifdef __cplusplus
11extern "C" {
12#endif
13
Erik Pilkingtonb6e16ea2019-03-18 19:23:45 +000014#if defined(USE_PASS_OBJECT_SIZE)
15void *memcpy(void *dst, const void *src, size_t c);
16static void *memcpy(void *dst __attribute__((pass_object_size(1))), const void *src, size_t c) __attribute__((overloadable)) __asm__("merp");
17static void *memcpy(void *const dst __attribute__((pass_object_size(1))), const void *src, size_t c) __attribute__((overloadable)) {
18 return 0;
19}
20#elif defined(USE_BUILTINS)
21#define memcpy(x,y,z) __builtin_memcpy(x,y,z)
22#else
23void *memcpy(void *dst, const void *src, size_t c);
24#endif
25
Erik Pilkington233ff942019-03-29 19:53:41 +000026#ifdef __cplusplus
27}
28#endif
29
Erik Pilkingtonb6e16ea2019-03-18 19:23:45 +000030void call_memcpy() {
31 char dst[10];
32 char src[20];
33 memcpy(dst, src, 20); // expected-warning {{memcpy' will always overflow; destination buffer has size 10, but size argument is 20}}
Erik Pilkington81869802019-03-26 23:21:22 +000034
35 if (sizeof(dst) == sizeof(src))
36 memcpy(dst, src, 20); // no warning, unreachable
Erik Pilkingtonb6e16ea2019-03-18 19:23:45 +000037}
38
39void call_memcpy_type() {
40 struct pair {
41 int first;
42 int second;
43 };
44 struct pair p;
45 char buf[20];
46 memcpy(&p.first, buf, 20);
47#ifdef USE_PASS_OBJECT_SIZE
48 // Use the more strict checking mode on the pass_object_size attribute:
49 // expected-warning@-3 {{memcpy' will always overflow; destination buffer has size 4, but size argument is 20}}
50#else
51 // Or just fallback to type 0:
52 // expected-warning@-6 {{memcpy' will always overflow; destination buffer has size 8, but size argument is 20}}
53#endif
54}
55
56void call_strncat() {
57 char s1[10], s2[20];
58 __builtin_strncat(s2, s1, 20);
59 __builtin_strncat(s1, s2, 20); // expected-warning {{'strncat' size argument is too large; destination buffer has size 10, but size argument is 20}}
60}
61
62void call_strncpy() {
63 char s1[10], s2[20];
64 __builtin_strncpy(s2, s1, 20);
65 __builtin_strncpy(s1, s2, 20); // expected-warning {{'strncpy' size argument is too large; destination buffer has size 10, but size argument is 20}}
66}
67
68void call_stpncpy() {
69 char s1[10], s2[20];
70 __builtin_stpncpy(s2, s1, 20);
71 __builtin_stpncpy(s1, s2, 20); // expected-warning {{'stpncpy' size argument is too large; destination buffer has size 10, but size argument is 20}}
72}
73
74void call_memmove() {
75 char s1[10], s2[20];
76 __builtin_memmove(s2, s1, 20);
77 __builtin_memmove(s1, s2, 20); // expected-warning {{'memmove' will always overflow; destination buffer has size 10, but size argument is 20}}
78}
79
80void call_memset() {
81 char buf[10];
82 __builtin_memset(buf, 0xff, 10);
83 __builtin_memset(buf, 0xff, 11); // expected-warning {{'memset' will always overflow; destination buffer has size 10, but size argument is 11}}
84}
85
86void call_snprintf() {
87 char buf[10];
88 __builtin_snprintf(buf, 10, "merp");
89 __builtin_snprintf(buf, 11, "merp"); // expected-warning {{'snprintf' size argument is too large; destination buffer has size 10, but size argument is 11}}
90}
91
92void call_vsnprintf() {
93 char buf[10];
94 __builtin_va_list list;
95 __builtin_vsnprintf(buf, 10, "merp", list);
96 __builtin_vsnprintf(buf, 11, "merp", list); // expected-warning {{'vsnprintf' size argument is too large; destination buffer has size 10, but size argument is 11}}
97}
Erik Pilkington233ff942019-03-29 19:53:41 +000098
99#ifdef __cplusplus
100template <class> struct S {
101 void mf() const {
102 __builtin_memset(const_cast<char *>(mv), 0, 0);
103 }
104
105 char mv[10];
106};
107
108template <int A, int B>
109void call_memcpy_dep() {
110 char bufferA[A];
111 char bufferB[B];
112 memcpy(bufferA, bufferB, 10); // expected-warning{{'memcpy' will always overflow; destination buffer has size 9, but size argument is 10}}
113}
114
115void call_call_memcpy() {
116 call_memcpy_dep<10, 9>();
117 call_memcpy_dep<9, 10>(); // expected-note {{in instantiation of function template specialization 'call_memcpy_dep<9, 10>' requested here}}
118}
119#endif