1 | // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s |
2 | // RUN: %clang_analyze_cc1 -DUSE_BUILTINS -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s |
3 | // RUN: %clang_analyze_cc1 -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,unix.Malloc,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s |
4 | // RUN: %clang_analyze_cc1 -DUSE_BUILTINS -DVARIANT -analyzer-checker=core,unix.cstring,alpha.unix.cstring,unix.Malloc,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s |
5 | // RUN: %clang_analyze_cc1 -DSUPPRESS_OUT_OF_BOUND -analyzer-checker=core,unix.cstring,unix.Malloc,alpha.unix.cstring.BufferOverlap,alpha.unix.cstring.NotNullTerminated,debug.ExprInspection -analyzer-store=region -verify -analyzer-config eagerly-assume=false %s |
6 | |
7 | #include "Inputs/system-header-simulator-cxx.h" |
8 | #include "Inputs/system-header-simulator-for-malloc.h" |
9 | |
10 | // This provides us with four possible mempcpy() definitions. |
11 | // See also comments in bstring.c. |
12 | |
13 | #ifdef USE_BUILTINS |
14 | #define BUILTIN(f) __builtin_##f |
15 | #else /* USE_BUILTINS */ |
16 | #define BUILTIN(f) f |
17 | #endif /* USE_BUILTINS */ |
18 | |
19 | #ifdef VARIANT |
20 | |
21 | #define __mempcpy_chk BUILTIN(__mempcpy_chk) |
22 | void *__mempcpy_chk(void *__restrict__ s1, const void *__restrict__ s2, |
23 | size_t n, size_t destlen); |
24 | |
25 | #define mempcpy(a,b,c) __mempcpy_chk(a,b,c,(size_t)-1) |
26 | |
27 | #else /* VARIANT */ |
28 | |
29 | #define mempcpy BUILTIN(mempcpy) |
30 | void *mempcpy(void *__restrict__ s1, const void *__restrict__ s2, size_t n); |
31 | |
32 | #endif /* VARIANT */ |
33 | |
34 | void clang_analyzer_eval(int); |
35 | |
36 | int *testStdCopyInvalidatesBuffer(std::vector<int> v) { |
37 | int n = v.size(); |
38 | int *buf = (int *)malloc(n * sizeof(int)); |
39 | |
40 | buf[0] = 66; |
41 | |
42 | // Call to copy should invalidate buf. |
43 | std::copy(v.begin(), v.end(), buf); |
44 | |
45 | int i = buf[0]; |
46 | |
47 | clang_analyzer_eval(i == 66); // expected-warning {{UNKNOWN}} |
48 | |
49 | return buf; |
50 | } |
51 | |
52 | int *testStdCopyBackwardInvalidatesBuffer(std::vector<int> v) { |
53 | int n = v.size(); |
54 | int *buf = (int *)malloc(n * sizeof(int)); |
55 | |
56 | buf[0] = 66; |
57 | |
58 | // Call to copy_backward should invalidate buf. |
59 | std::copy_backward(v.begin(), v.end(), buf + n); |
60 | |
61 | int i = buf[0]; |
62 | |
63 | clang_analyzer_eval(i == 66); // expected-warning {{UNKNOWN}} |
64 | |
65 | return buf; |
66 | } |
67 | |
68 | namespace pr34460 { |
69 | short a; |
70 | class b { |
71 | int c; |
72 | long g; |
73 | void d() { |
74 | int e = c; |
75 | f += e; |
76 | mempcpy(f, &a, g); |
77 | } |
78 | unsigned *f; |
79 | }; |
80 | } |
81 | |
82 | void *memset(void *dest, int ch, std::size_t count); |
83 | namespace memset_non_pod { |
84 | class Base { |
85 | public: |
86 | int b_mem; |
87 | Base() : b_mem(1) {} |
88 | }; |
89 | |
90 | class Derived : public Base { |
91 | public: |
92 | int d_mem; |
93 | Derived() : d_mem(2) {} |
94 | }; |
95 | |
96 | void memset1_inheritance() { |
97 | Derived d; |
98 | memset(&d, 0, sizeof(Derived)); |
99 | clang_analyzer_eval(d.b_mem == 0); // expected-warning{{TRUE}} |
100 | clang_analyzer_eval(d.d_mem == 0); // expected-warning{{TRUE}} |
101 | } |
102 | |
103 | #ifdef SUPPRESS_OUT_OF_BOUND |
104 | void memset2_inheritance_field() { |
105 | Derived d; |
106 | memset(&d.d_mem, 0, sizeof(Derived)); |
107 | clang_analyzer_eval(d.b_mem == 0); // expected-warning{{UNKNOWN}} |
108 | clang_analyzer_eval(d.d_mem == 0); // expected-warning{{UNKNOWN}} |
109 | } |
110 | |
111 | void memset3_inheritance_field() { |
112 | Derived d; |
113 | memset(&d.b_mem, 0, sizeof(Derived)); |
114 | clang_analyzer_eval(d.b_mem == 0); // expected-warning{{TRUE}} |
115 | clang_analyzer_eval(d.d_mem == 0); // expected-warning{{TRUE}} |
116 | } |
117 | #endif |
118 | |
119 | void memset4_array_nonpod_object() { |
120 | Derived array[10]; |
121 | clang_analyzer_eval(array[1].b_mem == 1); // expected-warning{{UNKNOWN}} |
122 | clang_analyzer_eval(array[1].d_mem == 2); // expected-warning{{UNKNOWN}} |
123 | memset(&array[1], 0, sizeof(Derived)); |
124 | clang_analyzer_eval(array[1].b_mem == 0); // expected-warning{{UNKNOWN}} |
125 | clang_analyzer_eval(array[1].d_mem == 0); // expected-warning{{UNKNOWN}} |
126 | } |
127 | |
128 | void memset5_array_nonpod_object() { |
129 | Derived array[10]; |
130 | clang_analyzer_eval(array[1].b_mem == 1); // expected-warning{{UNKNOWN}} |
131 | clang_analyzer_eval(array[1].d_mem == 2); // expected-warning{{UNKNOWN}} |
132 | memset(array, 0, sizeof(array)); |
133 | clang_analyzer_eval(array[1].b_mem == 0); // expected-warning{{TRUE}} |
134 | clang_analyzer_eval(array[1].d_mem == 0); // expected-warning{{TRUE}} |
135 | } |
136 | |
137 | void memset6_new_array_nonpod_object() { |
138 | Derived *array = new Derived[10]; |
139 | clang_analyzer_eval(array[2].b_mem == 1); // expected-warning{{UNKNOWN}} |
140 | clang_analyzer_eval(array[2].d_mem == 2); // expected-warning{{UNKNOWN}} |
141 | memset(array, 0, 10 * sizeof(Derived)); |
142 | clang_analyzer_eval(array[2].b_mem == 0); // expected-warning{{TRUE}} |
143 | clang_analyzer_eval(array[2].d_mem == 0); // expected-warning{{TRUE}} |
144 | delete[] array; |
145 | } |
146 | |
147 | void memset7_placement_new() { |
148 | Derived *d = new Derived(); |
149 | clang_analyzer_eval(d->b_mem == 1); // expected-warning{{TRUE}} |
150 | clang_analyzer_eval(d->d_mem == 2); // expected-warning{{TRUE}} |
151 | |
152 | memset(d, 0, sizeof(Derived)); |
153 | clang_analyzer_eval(d->b_mem == 0); // expected-warning{{TRUE}} |
154 | clang_analyzer_eval(d->d_mem == 0); // expected-warning{{TRUE}} |
155 | |
156 | Derived *d1 = new (d) Derived(); |
157 | clang_analyzer_eval(d1->b_mem == 1); // expected-warning{{TRUE}} |
158 | clang_analyzer_eval(d1->d_mem == 2); // expected-warning{{TRUE}} |
159 | |
160 | memset(d1, 0, sizeof(Derived)); |
161 | clang_analyzer_eval(d->b_mem == 0); // expected-warning{{TRUE}} |
162 | clang_analyzer_eval(d->d_mem == 0); // expected-warning{{TRUE}} |
163 | } |
164 | |
165 | class BaseVirtual { |
166 | public: |
167 | int b_mem; |
168 | virtual int get() { return 1; } |
169 | }; |
170 | |
171 | class DerivedVirtual : public BaseVirtual { |
172 | public: |
173 | int d_mem; |
174 | }; |
175 | |
176 | #ifdef SUPPRESS_OUT_OF_BOUND |
177 | void memset8_virtual_inheritance_field() { |
178 | DerivedVirtual d; |
179 | memset(&d.b_mem, 0, sizeof(Derived)); |
180 | clang_analyzer_eval(d.b_mem == 0); // expected-warning{{UNKNOWN}} |
181 | clang_analyzer_eval(d.d_mem == 0); // expected-warning{{UNKNOWN}} |
182 | } |
183 | #endif |
184 | } // namespace memset_non_pod |
185 | |
186 | #ifdef SUPPRESS_OUT_OF_BOUND |
187 | void memset1_new_array() { |
188 | int *array = new int[10]; |
189 | memset(array, 0, 10 * sizeof(int)); |
190 | clang_analyzer_eval(array[2] == 0); // expected-warning{{TRUE}} |
191 | memset(array + 1, 'a', 10 * sizeof(9)); |
192 | clang_analyzer_eval(array[2] == 0); // expected-warning{{UNKNOWN}} |
193 | delete[] array; |
194 | } |
195 | #endif |
196 | |