1 | //===-- tsan_mman_test.cpp ------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file is a part of ThreadSanitizer (TSan), a race detector. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | #include <limits> |
13 | #include <sanitizer/allocator_interface.h> |
14 | #include "tsan_mman.h" |
15 | #include "tsan_rtl.h" |
16 | #include "gtest/gtest.h" |
17 | |
18 | namespace __tsan { |
19 | |
20 | TEST(Mman, Internal) { |
21 | char *p = (char *)Alloc(10); |
22 | EXPECT_NE(p, (char*)0); |
23 | char *p2 = (char *)Alloc(20); |
24 | EXPECT_NE(p2, (char*)0); |
25 | EXPECT_NE(p2, p); |
26 | for (int i = 0; i < 10; i++) { |
27 | p[i] = 42; |
28 | } |
29 | for (int i = 0; i < 20; i++) { |
30 | ((char*)p2)[i] = 42; |
31 | } |
32 | Free(p); |
33 | Free(p2); |
34 | } |
35 | |
36 | TEST(Mman, User) { |
37 | ThreadState *thr = cur_thread(); |
38 | uptr pc = 0; |
39 | char *p = (char*)user_alloc(thr, pc, 10); |
40 | EXPECT_NE(p, (char*)0); |
41 | char *p2 = (char*)user_alloc(thr, pc, 20); |
42 | EXPECT_NE(p2, (char*)0); |
43 | EXPECT_NE(p2, p); |
44 | EXPECT_EQ(10U, user_alloc_usable_size(p)); |
45 | EXPECT_EQ(20U, user_alloc_usable_size(p2)); |
46 | user_free(thr, pc, p); |
47 | user_free(thr, pc, p2); |
48 | } |
49 | |
50 | TEST(Mman, UserRealloc) { |
51 | ThreadState *thr = cur_thread(); |
52 | uptr pc = 0; |
53 | { |
54 | void *p = user_realloc(thr, pc, 0, 0); |
55 | // Realloc(NULL, N) is equivalent to malloc(N), thus must return |
56 | // non-NULL pointer. |
57 | EXPECT_NE(p, (void*)0); |
58 | user_free(thr, pc, p); |
59 | } |
60 | { |
61 | void *p = user_realloc(thr, pc, 0, 100); |
62 | EXPECT_NE(p, (void*)0); |
63 | memset(p, 0xde, 100); |
64 | user_free(thr, pc, p); |
65 | } |
66 | { |
67 | void *p = user_alloc(thr, pc, 100); |
68 | EXPECT_NE(p, (void*)0); |
69 | memset(p, 0xde, 100); |
70 | // Realloc(P, 0) is equivalent to free(P) and returns NULL. |
71 | void *p2 = user_realloc(thr, pc, p, 0); |
72 | EXPECT_EQ(p2, (void*)0); |
73 | } |
74 | { |
75 | void *p = user_realloc(thr, pc, 0, 100); |
76 | EXPECT_NE(p, (void*)0); |
77 | memset(p, 0xde, 100); |
78 | void *p2 = user_realloc(thr, pc, p, 10000); |
79 | EXPECT_NE(p2, (void*)0); |
80 | for (int i = 0; i < 100; i++) |
81 | EXPECT_EQ(((char*)p2)[i], (char)0xde); |
82 | memset(p2, 0xde, 10000); |
83 | user_free(thr, pc, p2); |
84 | } |
85 | { |
86 | void *p = user_realloc(thr, pc, 0, 10000); |
87 | EXPECT_NE(p, (void*)0); |
88 | memset(p, 0xde, 10000); |
89 | void *p2 = user_realloc(thr, pc, p, 10); |
90 | EXPECT_NE(p2, (void*)0); |
91 | for (int i = 0; i < 10; i++) |
92 | EXPECT_EQ(((char*)p2)[i], (char)0xde); |
93 | user_free(thr, pc, p2); |
94 | } |
95 | } |
96 | |
97 | TEST(Mman, UsableSize) { |
98 | ThreadState *thr = cur_thread(); |
99 | uptr pc = 0; |
100 | char *p = (char*)user_alloc(thr, pc, 10); |
101 | char *p2 = (char*)user_alloc(thr, pc, 20); |
102 | EXPECT_EQ(0U, user_alloc_usable_size(NULL)); |
103 | EXPECT_EQ(10U, user_alloc_usable_size(p)); |
104 | EXPECT_EQ(20U, user_alloc_usable_size(p2)); |
105 | user_free(thr, pc, p); |
106 | user_free(thr, pc, p2); |
107 | EXPECT_EQ(0U, user_alloc_usable_size((void*)0x4123)); |
108 | } |
109 | |
110 | TEST(Mman, Stats) { |
111 | ThreadState *thr = cur_thread(); |
112 | |
113 | uptr alloc0 = __sanitizer_get_current_allocated_bytes(); |
114 | uptr heap0 = __sanitizer_get_heap_size(); |
115 | uptr free0 = __sanitizer_get_free_bytes(); |
116 | uptr unmapped0 = __sanitizer_get_unmapped_bytes(); |
117 | |
118 | EXPECT_EQ(10U, __sanitizer_get_estimated_allocated_size(size: 10)); |
119 | EXPECT_EQ(20U, __sanitizer_get_estimated_allocated_size(size: 20)); |
120 | EXPECT_EQ(100U, __sanitizer_get_estimated_allocated_size(size: 100)); |
121 | |
122 | char *p = (char*)user_alloc(thr, 0, 10); |
123 | EXPECT_TRUE(__sanitizer_get_ownership(p)); |
124 | EXPECT_EQ(10U, __sanitizer_get_allocated_size(p)); |
125 | |
126 | EXPECT_EQ(alloc0 + 16, __sanitizer_get_current_allocated_bytes()); |
127 | EXPECT_GE(__sanitizer_get_heap_size(), heap0); |
128 | EXPECT_EQ(free0, __sanitizer_get_free_bytes()); |
129 | EXPECT_EQ(unmapped0, __sanitizer_get_unmapped_bytes()); |
130 | |
131 | user_free(thr, 0, p); |
132 | |
133 | EXPECT_EQ(alloc0, __sanitizer_get_current_allocated_bytes()); |
134 | EXPECT_GE(__sanitizer_get_heap_size(), heap0); |
135 | EXPECT_EQ(free0, __sanitizer_get_free_bytes()); |
136 | EXPECT_EQ(unmapped0, __sanitizer_get_unmapped_bytes()); |
137 | } |
138 | |
139 | TEST(Mman, Valloc) { |
140 | ThreadState *thr = cur_thread(); |
141 | uptr page_size = GetPageSizeCached(); |
142 | |
143 | void *p = user_valloc(thr, 0, 100); |
144 | EXPECT_NE(p, (void*)0); |
145 | user_free(thr, 0, p); |
146 | |
147 | p = user_pvalloc(thr, 0, 100); |
148 | EXPECT_NE(p, (void*)0); |
149 | user_free(thr, 0, p); |
150 | |
151 | p = user_pvalloc(thr, 0, 0); |
152 | EXPECT_NE(p, (void*)0); |
153 | EXPECT_EQ(page_size, __sanitizer_get_allocated_size(p)); |
154 | user_free(thr, 0, p); |
155 | } |
156 | |
157 | #if !SANITIZER_DEBUG |
158 | // EXPECT_DEATH clones a thread with 4K stack, |
159 | // which is overflown by tsan memory accesses functions in debug mode. |
160 | |
161 | TEST(Mman, Memalign) { |
162 | ThreadState *thr = cur_thread(); |
163 | |
164 | void *p = user_memalign(thr, 0, 8, 100); |
165 | EXPECT_NE(p, (void*)0); |
166 | user_free(thr, 0, p); |
167 | |
168 | // TODO(alekseyshl): Remove this death test when memalign is verified by |
169 | // tests in sanitizer_common. |
170 | p = NULL; |
171 | EXPECT_DEATH(p = user_memalign(thr, 0, 7, 100), |
172 | "invalid-allocation-alignment" ); |
173 | EXPECT_EQ(0L, p); |
174 | } |
175 | |
176 | #endif |
177 | |
178 | TEST(Mman, PosixMemalign) { |
179 | ThreadState *thr = cur_thread(); |
180 | |
181 | void *p = NULL; |
182 | int res = user_posix_memalign(thr, 0, &p, 8, 100); |
183 | EXPECT_NE(p, (void*)0); |
184 | EXPECT_EQ(res, 0); |
185 | user_free(thr, 0, p); |
186 | } |
187 | |
188 | TEST(Mman, AlignedAlloc) { |
189 | ThreadState *thr = cur_thread(); |
190 | |
191 | void *p = user_aligned_alloc(thr, 0, 8, 64); |
192 | EXPECT_NE(p, (void*)0); |
193 | user_free(thr, 0, p); |
194 | } |
195 | |
196 | } // namespace __tsan |
197 | |