1//===-- tsan_mman_test.cc -------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of ThreadSanitizer (TSan), a race detector.
11//
12//===----------------------------------------------------------------------===//
13#include <limits>
14#include <sanitizer/allocator_interface.h>
15#include "tsan_mman.h"
16#include "tsan_rtl.h"
17#include "gtest/gtest.h"
18
19namespace __tsan {
20
21TEST(Mman, Internal) {
22  char *p = (char*)internal_alloc(MBlockScopedBuf, 10);
23  EXPECT_NE(p, (char*)0);
24  char *p2 = (char*)internal_alloc(MBlockScopedBuf, 20);
25  EXPECT_NE(p2, (char*)0);
26  EXPECT_NE(p2, p);
27  for (int i = 0; i < 10; i++) {
28    p[i] = 42;
29  }
30  for (int i = 0; i < 20; i++) {
31    ((char*)p2)[i] = 42;
32  }
33  internal_free(p);
34  internal_free(p2);
35}
36
37TEST(Mman, User) {
38  ThreadState *thr = cur_thread();
39  uptr pc = 0;
40  char *p = (char*)user_alloc(thr, pc, 10);
41  EXPECT_NE(p, (char*)0);
42  char *p2 = (char*)user_alloc(thr, pc, 20);
43  EXPECT_NE(p2, (char*)0);
44  EXPECT_NE(p2, p);
45  EXPECT_EQ(10U, user_alloc_usable_size(p));
46  EXPECT_EQ(20U, user_alloc_usable_size(p2));
47  user_free(thr, pc, p);
48  user_free(thr, pc, p2);
49}
50
51TEST(Mman, UserRealloc) {
52  ThreadState *thr = cur_thread();
53  uptr pc = 0;
54  {
55    void *p = user_realloc(thr, pc, 0, 0);
56    // Strictly saying this is incorrect, realloc(NULL, N) is equivalent to
57    // malloc(N), thus must return non-NULL pointer.
58    EXPECT_EQ(p, (void*)0);
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    void *p2 = user_realloc(thr, pc, p, 0);
71    EXPECT_EQ(p2, (void*)0);
72  }
73  {
74    void *p = user_realloc(thr, pc, 0, 100);
75    EXPECT_NE(p, (void*)0);
76    memset(p, 0xde, 100);
77    void *p2 = user_realloc(thr, pc, p, 10000);
78    EXPECT_NE(p2, (void*)0);
79    for (int i = 0; i < 100; i++)
80      EXPECT_EQ(((char*)p2)[i], (char)0xde);
81    memset(p2, 0xde, 10000);
82    user_free(thr, pc, p2);
83  }
84  {
85    void *p = user_realloc(thr, pc, 0, 10000);
86    EXPECT_NE(p, (void*)0);
87    memset(p, 0xde, 10000);
88    void *p2 = user_realloc(thr, pc, p, 10);
89    EXPECT_NE(p2, (void*)0);
90    for (int i = 0; i < 10; i++)
91      EXPECT_EQ(((char*)p2)[i], (char)0xde);
92    user_free(thr, pc, p2);
93  }
94}
95
96TEST(Mman, UsableSize) {
97  ThreadState *thr = cur_thread();
98  uptr pc = 0;
99  char *p = (char*)user_alloc(thr, pc, 10);
100  char *p2 = (char*)user_alloc(thr, pc, 20);
101  EXPECT_EQ(0U, user_alloc_usable_size(NULL));
102  EXPECT_EQ(10U, user_alloc_usable_size(p));
103  EXPECT_EQ(20U, user_alloc_usable_size(p2));
104  user_free(thr, pc, p);
105  user_free(thr, pc, p2);
106  EXPECT_EQ(0U, user_alloc_usable_size((void*)0x123));
107}
108
109TEST(Mman, Stats) {
110  ThreadState *thr = cur_thread();
111
112  uptr alloc0 = __sanitizer_get_current_allocated_bytes();
113  uptr heap0 = __sanitizer_get_heap_size();
114  uptr free0 = __sanitizer_get_free_bytes();
115  uptr unmapped0 = __sanitizer_get_unmapped_bytes();
116
117  EXPECT_EQ(10U, __sanitizer_get_estimated_allocated_size(10));
118  EXPECT_EQ(20U, __sanitizer_get_estimated_allocated_size(20));
119  EXPECT_EQ(100U, __sanitizer_get_estimated_allocated_size(100));
120
121  char *p = (char*)user_alloc(thr, 0, 10);
122  EXPECT_TRUE(__sanitizer_get_ownership(p));
123  EXPECT_EQ(10U, __sanitizer_get_allocated_size(p));
124
125  EXPECT_EQ(alloc0 + 16, __sanitizer_get_current_allocated_bytes());
126  EXPECT_GE(__sanitizer_get_heap_size(), heap0);
127  EXPECT_EQ(free0, __sanitizer_get_free_bytes());
128  EXPECT_EQ(unmapped0, __sanitizer_get_unmapped_bytes());
129
130  user_free(thr, 0, p);
131
132  EXPECT_EQ(alloc0, __sanitizer_get_current_allocated_bytes());
133  EXPECT_GE(__sanitizer_get_heap_size(), heap0);
134  EXPECT_EQ(free0, __sanitizer_get_free_bytes());
135  EXPECT_EQ(unmapped0, __sanitizer_get_unmapped_bytes());
136}
137
138TEST(Mman, CallocOverflow) {
139#if TSAN_DEBUG
140  // EXPECT_DEATH clones a thread with 4K stack,
141  // which is overflown by tsan memory accesses functions in debug mode.
142  return;
143#endif
144  size_t kArraySize = 4096;
145  volatile size_t kMaxSizeT = std::numeric_limits<size_t>::max();
146  volatile size_t kArraySize2 = kMaxSizeT / kArraySize + 10;
147  volatile void *p = NULL;
148  EXPECT_DEATH(p = calloc(kArraySize, kArraySize2),
149               "allocator is terminating the process instead of returning 0");
150  EXPECT_EQ(0L, p);
151}
152
153}  // namespace __tsan
154