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 | |
5 | typedef unsigned long size_t; |
6 | |
7 | #if defined(USE_PASS_OBJECT_SIZE) |
8 | void *memcpy(void *dst, const void *src, size_t c); |
9 | static void *memcpy(void *dst __attribute__((pass_object_size(1))), const void *src, size_t c) __attribute__((overloadable)) __asm__("merp"); |
10 | static void *memcpy(void *const dst __attribute__((pass_object_size(1))), const void *src, size_t c) __attribute__((overloadable)) { |
11 | return 0; |
12 | } |
13 | #elif defined(USE_BUILTINS) |
14 | #define memcpy(x,y,z) __builtin_memcpy(x,y,z) |
15 | #else |
16 | void *memcpy(void *dst, const void *src, size_t c); |
17 | #endif |
18 | |
19 | void call_memcpy() { |
20 | char dst[10]; |
21 | char src[20]; |
22 | memcpy(dst, src, 20); // expected-warning {{memcpy' will always overflow; destination buffer has size 10, but size argument is 20}} |
23 | |
24 | if (sizeof(dst) == sizeof(src)) |
25 | memcpy(dst, src, 20); // no warning, unreachable |
26 | } |
27 | |
28 | void call_memcpy_type() { |
29 | struct pair { |
30 | int first; |
31 | int second; |
32 | }; |
33 | struct pair p; |
34 | char buf[20]; |
35 | memcpy(&p.first, buf, 20); |
36 | #ifdef USE_PASS_OBJECT_SIZE |
37 | // Use the more strict checking mode on the pass_object_size attribute: |
38 | // expected-warning@-3 {{memcpy' will always overflow; destination buffer has size 4, but size argument is 20}} |
39 | #else |
40 | // Or just fallback to type 0: |
41 | // expected-warning@-6 {{memcpy' will always overflow; destination buffer has size 8, but size argument is 20}} |
42 | #endif |
43 | } |
44 | |
45 | void call_strncat() { |
46 | char s1[10], s2[20]; |
47 | __builtin_strncat(s2, s1, 20); |
48 | __builtin_strncat(s1, s2, 20); // expected-warning {{'strncat' size argument is too large; destination buffer has size 10, but size argument is 20}} |
49 | } |
50 | |
51 | void call_strncpy() { |
52 | char s1[10], s2[20]; |
53 | __builtin_strncpy(s2, s1, 20); |
54 | __builtin_strncpy(s1, s2, 20); // expected-warning {{'strncpy' size argument is too large; destination buffer has size 10, but size argument is 20}} |
55 | } |
56 | |
57 | void call_stpncpy() { |
58 | char s1[10], s2[20]; |
59 | __builtin_stpncpy(s2, s1, 20); |
60 | __builtin_stpncpy(s1, s2, 20); // expected-warning {{'stpncpy' size argument is too large; destination buffer has size 10, but size argument is 20}} |
61 | } |
62 | |
63 | void call_memmove() { |
64 | char s1[10], s2[20]; |
65 | __builtin_memmove(s2, s1, 20); |
66 | __builtin_memmove(s1, s2, 20); // expected-warning {{'memmove' will always overflow; destination buffer has size 10, but size argument is 20}} |
67 | } |
68 | |
69 | void call_memset() { |
70 | char buf[10]; |
71 | __builtin_memset(buf, 0xff, 10); |
72 | __builtin_memset(buf, 0xff, 11); // expected-warning {{'memset' will always overflow; destination buffer has size 10, but size argument is 11}} |
73 | } |
74 | |
75 | void call_snprintf() { |
76 | char buf[10]; |
77 | __builtin_snprintf(buf, 10, "merp"); |
78 | __builtin_snprintf(buf, 11, "merp"); // expected-warning {{'snprintf' size argument is too large; destination buffer has size 10, but size argument is 11}} |
79 | } |
80 | |
81 | void call_vsnprintf() { |
82 | char buf[10]; |
83 | __builtin_va_list list; |
84 | __builtin_vsnprintf(buf, 10, "merp", list); |
85 | __builtin_vsnprintf(buf, 11, "merp", list); // expected-warning {{'vsnprintf' size argument is too large; destination buffer has size 10, but size argument is 11}} |
86 | } |
87 | |