xref: /aosp_15_r20/external/scudo/standalone/tests/wrappers_c_test.cpp (revision 76559068c068bd27e82aff38fac3bfc865233bca)
1*76559068SAndroid Build Coastguard Worker //===-- wrappers_c_test.cpp -------------------------------------*- C++ -*-===//
2*76559068SAndroid Build Coastguard Worker //
3*76559068SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*76559068SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information.
5*76559068SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*76559068SAndroid Build Coastguard Worker //
7*76559068SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
8*76559068SAndroid Build Coastguard Worker 
9*76559068SAndroid Build Coastguard Worker #include "common.h"
10*76559068SAndroid Build Coastguard Worker #include "memtag.h"
11*76559068SAndroid Build Coastguard Worker #include "scudo/interface.h"
12*76559068SAndroid Build Coastguard Worker #include "tests/scudo_unit_test.h"
13*76559068SAndroid Build Coastguard Worker 
14*76559068SAndroid Build Coastguard Worker #include <errno.h>
15*76559068SAndroid Build Coastguard Worker #include <limits.h>
16*76559068SAndroid Build Coastguard Worker #include <malloc.h>
17*76559068SAndroid Build Coastguard Worker #include <stdlib.h>
18*76559068SAndroid Build Coastguard Worker #include <unistd.h>
19*76559068SAndroid Build Coastguard Worker #include <vector>
20*76559068SAndroid Build Coastguard Worker 
21*76559068SAndroid Build Coastguard Worker #ifndef __GLIBC_PREREQ
22*76559068SAndroid Build Coastguard Worker #define __GLIBC_PREREQ(x, y) 0
23*76559068SAndroid Build Coastguard Worker #endif
24*76559068SAndroid Build Coastguard Worker 
25*76559068SAndroid Build Coastguard Worker #if SCUDO_FUCHSIA
26*76559068SAndroid Build Coastguard Worker // Fuchsia only has valloc
27*76559068SAndroid Build Coastguard Worker #define HAVE_VALLOC 1
28*76559068SAndroid Build Coastguard Worker #elif SCUDO_ANDROID
29*76559068SAndroid Build Coastguard Worker // Android only has pvalloc/valloc on 32 bit
30*76559068SAndroid Build Coastguard Worker #if !defined(__LP64__)
31*76559068SAndroid Build Coastguard Worker #define HAVE_PVALLOC 1
32*76559068SAndroid Build Coastguard Worker #define HAVE_VALLOC 1
33*76559068SAndroid Build Coastguard Worker #endif // !defined(__LP64__)
34*76559068SAndroid Build Coastguard Worker #else
35*76559068SAndroid Build Coastguard Worker // All others assumed to support both functions.
36*76559068SAndroid Build Coastguard Worker #define HAVE_PVALLOC 1
37*76559068SAndroid Build Coastguard Worker #define HAVE_VALLOC 1
38*76559068SAndroid Build Coastguard Worker #endif
39*76559068SAndroid Build Coastguard Worker 
40*76559068SAndroid Build Coastguard Worker extern "C" {
41*76559068SAndroid Build Coastguard Worker void malloc_enable(void);
42*76559068SAndroid Build Coastguard Worker void malloc_disable(void);
43*76559068SAndroid Build Coastguard Worker int malloc_iterate(uintptr_t base, size_t size,
44*76559068SAndroid Build Coastguard Worker                    void (*callback)(uintptr_t base, size_t size, void *arg),
45*76559068SAndroid Build Coastguard Worker                    void *arg);
46*76559068SAndroid Build Coastguard Worker void *valloc(size_t size);
47*76559068SAndroid Build Coastguard Worker void *pvalloc(size_t size);
48*76559068SAndroid Build Coastguard Worker 
49*76559068SAndroid Build Coastguard Worker #ifndef SCUDO_ENABLE_HOOKS_TESTS
50*76559068SAndroid Build Coastguard Worker #define SCUDO_ENABLE_HOOKS_TESTS 0
51*76559068SAndroid Build Coastguard Worker #endif
52*76559068SAndroid Build Coastguard Worker 
53*76559068SAndroid Build Coastguard Worker #if (SCUDO_ENABLE_HOOKS_TESTS == 1) && (SCUDO_ENABLE_HOOKS == 0)
54*76559068SAndroid Build Coastguard Worker #error "Hooks tests should have hooks enabled as well!"
55*76559068SAndroid Build Coastguard Worker #endif
56*76559068SAndroid Build Coastguard Worker 
57*76559068SAndroid Build Coastguard Worker struct AllocContext {
58*76559068SAndroid Build Coastguard Worker   void *Ptr;
59*76559068SAndroid Build Coastguard Worker   size_t Size;
60*76559068SAndroid Build Coastguard Worker };
61*76559068SAndroid Build Coastguard Worker struct DeallocContext {
62*76559068SAndroid Build Coastguard Worker   void *Ptr;
63*76559068SAndroid Build Coastguard Worker };
64*76559068SAndroid Build Coastguard Worker struct ReallocContext {
65*76559068SAndroid Build Coastguard Worker   void *AllocPtr;
66*76559068SAndroid Build Coastguard Worker   void *DeallocPtr;
67*76559068SAndroid Build Coastguard Worker   size_t Size;
68*76559068SAndroid Build Coastguard Worker };
69*76559068SAndroid Build Coastguard Worker static AllocContext AC;
70*76559068SAndroid Build Coastguard Worker static DeallocContext DC;
71*76559068SAndroid Build Coastguard Worker static ReallocContext RC;
72*76559068SAndroid Build Coastguard Worker 
73*76559068SAndroid Build Coastguard Worker #if (SCUDO_ENABLE_HOOKS_TESTS == 1)
__scudo_allocate_hook(void * Ptr,size_t Size)74*76559068SAndroid Build Coastguard Worker __attribute__((visibility("default"))) void __scudo_allocate_hook(void *Ptr,
75*76559068SAndroid Build Coastguard Worker                                                                   size_t Size) {
76*76559068SAndroid Build Coastguard Worker   AC.Ptr = Ptr;
77*76559068SAndroid Build Coastguard Worker   AC.Size = Size;
78*76559068SAndroid Build Coastguard Worker }
__scudo_deallocate_hook(void * Ptr)79*76559068SAndroid Build Coastguard Worker __attribute__((visibility("default"))) void __scudo_deallocate_hook(void *Ptr) {
80*76559068SAndroid Build Coastguard Worker   DC.Ptr = Ptr;
81*76559068SAndroid Build Coastguard Worker }
82*76559068SAndroid Build Coastguard Worker __attribute__((visibility("default"))) void
__scudo_realloc_allocate_hook(void * OldPtr,void * NewPtr,size_t Size)83*76559068SAndroid Build Coastguard Worker __scudo_realloc_allocate_hook(void *OldPtr, void *NewPtr, size_t Size) {
84*76559068SAndroid Build Coastguard Worker   // Verify that __scudo_realloc_deallocate_hook is called first and set the
85*76559068SAndroid Build Coastguard Worker   // right pointer.
86*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(OldPtr, RC.DeallocPtr);
87*76559068SAndroid Build Coastguard Worker   RC.AllocPtr = NewPtr;
88*76559068SAndroid Build Coastguard Worker   RC.Size = Size;
89*76559068SAndroid Build Coastguard Worker 
90*76559068SAndroid Build Coastguard Worker   // Note that this is only used for testing. In general, only one pair of hooks
91*76559068SAndroid Build Coastguard Worker   // will be invoked in `realloc`. if __scudo_realloc_*_hook are not defined,
92*76559068SAndroid Build Coastguard Worker   // it'll call the general hooks only. To make the test easier, we call the
93*76559068SAndroid Build Coastguard Worker   // general one here so that either case (whether __scudo_realloc_*_hook are
94*76559068SAndroid Build Coastguard Worker   // defined) will be verified without separating them into different tests.
95*76559068SAndroid Build Coastguard Worker   __scudo_allocate_hook(NewPtr, Size);
96*76559068SAndroid Build Coastguard Worker }
97*76559068SAndroid Build Coastguard Worker __attribute__((visibility("default"))) void
__scudo_realloc_deallocate_hook(void * Ptr)98*76559068SAndroid Build Coastguard Worker __scudo_realloc_deallocate_hook(void *Ptr) {
99*76559068SAndroid Build Coastguard Worker   RC.DeallocPtr = Ptr;
100*76559068SAndroid Build Coastguard Worker 
101*76559068SAndroid Build Coastguard Worker   // See the comment in the __scudo_realloc_allocate_hook above.
102*76559068SAndroid Build Coastguard Worker   __scudo_deallocate_hook(Ptr);
103*76559068SAndroid Build Coastguard Worker }
104*76559068SAndroid Build Coastguard Worker #endif // (SCUDO_ENABLE_HOOKS_TESTS == 1)
105*76559068SAndroid Build Coastguard Worker }
106*76559068SAndroid Build Coastguard Worker 
107*76559068SAndroid Build Coastguard Worker class ScudoWrappersCTest : public Test {
108*76559068SAndroid Build Coastguard Worker protected:
SetUp()109*76559068SAndroid Build Coastguard Worker   void SetUp() override {
110*76559068SAndroid Build Coastguard Worker     if (SCUDO_ENABLE_HOOKS && !SCUDO_ENABLE_HOOKS_TESTS)
111*76559068SAndroid Build Coastguard Worker       printf("Hooks are enabled but hooks tests are disabled.\n");
112*76559068SAndroid Build Coastguard Worker   }
113*76559068SAndroid Build Coastguard Worker 
invalidateHookPtrs()114*76559068SAndroid Build Coastguard Worker   void invalidateHookPtrs() {
115*76559068SAndroid Build Coastguard Worker     if (SCUDO_ENABLE_HOOKS_TESTS) {
116*76559068SAndroid Build Coastguard Worker       void *InvalidPtr = reinterpret_cast<void *>(0xdeadbeef);
117*76559068SAndroid Build Coastguard Worker       AC.Ptr = InvalidPtr;
118*76559068SAndroid Build Coastguard Worker       DC.Ptr = InvalidPtr;
119*76559068SAndroid Build Coastguard Worker       RC.AllocPtr = RC.DeallocPtr = InvalidPtr;
120*76559068SAndroid Build Coastguard Worker     }
121*76559068SAndroid Build Coastguard Worker   }
verifyAllocHookPtr(UNUSED void * Ptr)122*76559068SAndroid Build Coastguard Worker   void verifyAllocHookPtr(UNUSED void *Ptr) {
123*76559068SAndroid Build Coastguard Worker     if (SCUDO_ENABLE_HOOKS_TESTS)
124*76559068SAndroid Build Coastguard Worker       EXPECT_EQ(Ptr, AC.Ptr);
125*76559068SAndroid Build Coastguard Worker   }
verifyAllocHookSize(UNUSED size_t Size)126*76559068SAndroid Build Coastguard Worker   void verifyAllocHookSize(UNUSED size_t Size) {
127*76559068SAndroid Build Coastguard Worker     if (SCUDO_ENABLE_HOOKS_TESTS)
128*76559068SAndroid Build Coastguard Worker       EXPECT_EQ(Size, AC.Size);
129*76559068SAndroid Build Coastguard Worker   }
verifyDeallocHookPtr(UNUSED void * Ptr)130*76559068SAndroid Build Coastguard Worker   void verifyDeallocHookPtr(UNUSED void *Ptr) {
131*76559068SAndroid Build Coastguard Worker     if (SCUDO_ENABLE_HOOKS_TESTS)
132*76559068SAndroid Build Coastguard Worker       EXPECT_EQ(Ptr, DC.Ptr);
133*76559068SAndroid Build Coastguard Worker   }
verifyReallocHookPtrs(UNUSED void * OldPtr,void * NewPtr,size_t Size)134*76559068SAndroid Build Coastguard Worker   void verifyReallocHookPtrs(UNUSED void *OldPtr, void *NewPtr, size_t Size) {
135*76559068SAndroid Build Coastguard Worker     if (SCUDO_ENABLE_HOOKS_TESTS) {
136*76559068SAndroid Build Coastguard Worker       EXPECT_EQ(OldPtr, RC.DeallocPtr);
137*76559068SAndroid Build Coastguard Worker       EXPECT_EQ(NewPtr, RC.AllocPtr);
138*76559068SAndroid Build Coastguard Worker       EXPECT_EQ(Size, RC.Size);
139*76559068SAndroid Build Coastguard Worker     }
140*76559068SAndroid Build Coastguard Worker   }
141*76559068SAndroid Build Coastguard Worker };
142*76559068SAndroid Build Coastguard Worker using ScudoWrappersCDeathTest = ScudoWrappersCTest;
143*76559068SAndroid Build Coastguard Worker 
144*76559068SAndroid Build Coastguard Worker // Note that every C allocation function in the test binary will be fulfilled
145*76559068SAndroid Build Coastguard Worker // by Scudo (this includes the gtest APIs, etc.), which is a test by itself.
146*76559068SAndroid Build Coastguard Worker // But this might also lead to unexpected side-effects, since the allocation and
147*76559068SAndroid Build Coastguard Worker // deallocation operations in the TEST functions will coexist with others (see
148*76559068SAndroid Build Coastguard Worker // the EXPECT_DEATH comment below).
149*76559068SAndroid Build Coastguard Worker 
150*76559068SAndroid Build Coastguard Worker // We have to use a small quarantine to make sure that our double-free tests
151*76559068SAndroid Build Coastguard Worker // trigger. Otherwise EXPECT_DEATH ends up reallocating the chunk that was just
152*76559068SAndroid Build Coastguard Worker // freed (this depends on the size obviously) and the following free succeeds.
153*76559068SAndroid Build Coastguard Worker 
154*76559068SAndroid Build Coastguard Worker static const size_t Size = 100U;
155*76559068SAndroid Build Coastguard Worker 
TEST_F(ScudoWrappersCDeathTest,Malloc)156*76559068SAndroid Build Coastguard Worker TEST_F(ScudoWrappersCDeathTest, Malloc) {
157*76559068SAndroid Build Coastguard Worker   void *P = malloc(Size);
158*76559068SAndroid Build Coastguard Worker   EXPECT_NE(P, nullptr);
159*76559068SAndroid Build Coastguard Worker   EXPECT_LE(Size, malloc_usable_size(P));
160*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(reinterpret_cast<uintptr_t>(P) % FIRST_32_SECOND_64(8U, 16U), 0U);
161*76559068SAndroid Build Coastguard Worker   verifyAllocHookPtr(P);
162*76559068SAndroid Build Coastguard Worker   verifyAllocHookSize(Size);
163*76559068SAndroid Build Coastguard Worker 
164*76559068SAndroid Build Coastguard Worker   // An update to this warning in Clang now triggers in this line, but it's ok
165*76559068SAndroid Build Coastguard Worker   // because the check is expecting a bad pointer and should fail.
166*76559068SAndroid Build Coastguard Worker #if defined(__has_warning) && __has_warning("-Wfree-nonheap-object")
167*76559068SAndroid Build Coastguard Worker #pragma GCC diagnostic push
168*76559068SAndroid Build Coastguard Worker #pragma GCC diagnostic ignored "-Wfree-nonheap-object"
169*76559068SAndroid Build Coastguard Worker #endif
170*76559068SAndroid Build Coastguard Worker   EXPECT_DEATH(
171*76559068SAndroid Build Coastguard Worker       free(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(P) | 1U)), "");
172*76559068SAndroid Build Coastguard Worker #if defined(__has_warning) && __has_warning("-Wfree-nonheap-object")
173*76559068SAndroid Build Coastguard Worker #pragma GCC diagnostic pop
174*76559068SAndroid Build Coastguard Worker #endif
175*76559068SAndroid Build Coastguard Worker 
176*76559068SAndroid Build Coastguard Worker   free(P);
177*76559068SAndroid Build Coastguard Worker   verifyDeallocHookPtr(P);
178*76559068SAndroid Build Coastguard Worker   EXPECT_DEATH(free(P), "");
179*76559068SAndroid Build Coastguard Worker 
180*76559068SAndroid Build Coastguard Worker   P = malloc(0U);
181*76559068SAndroid Build Coastguard Worker   EXPECT_NE(P, nullptr);
182*76559068SAndroid Build Coastguard Worker   free(P);
183*76559068SAndroid Build Coastguard Worker 
184*76559068SAndroid Build Coastguard Worker   errno = 0;
185*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(malloc(SIZE_MAX), nullptr);
186*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(errno, ENOMEM);
187*76559068SAndroid Build Coastguard Worker }
188*76559068SAndroid Build Coastguard Worker 
TEST_F(ScudoWrappersCTest,Calloc)189*76559068SAndroid Build Coastguard Worker TEST_F(ScudoWrappersCTest, Calloc) {
190*76559068SAndroid Build Coastguard Worker   void *P = calloc(1U, Size);
191*76559068SAndroid Build Coastguard Worker   EXPECT_NE(P, nullptr);
192*76559068SAndroid Build Coastguard Worker   EXPECT_LE(Size, malloc_usable_size(P));
193*76559068SAndroid Build Coastguard Worker   verifyAllocHookPtr(P);
194*76559068SAndroid Build Coastguard Worker   verifyAllocHookSize(Size);
195*76559068SAndroid Build Coastguard Worker   for (size_t I = 0; I < Size; I++)
196*76559068SAndroid Build Coastguard Worker     EXPECT_EQ((reinterpret_cast<uint8_t *>(P))[I], 0U);
197*76559068SAndroid Build Coastguard Worker   free(P);
198*76559068SAndroid Build Coastguard Worker   verifyDeallocHookPtr(P);
199*76559068SAndroid Build Coastguard Worker 
200*76559068SAndroid Build Coastguard Worker   P = calloc(1U, 0U);
201*76559068SAndroid Build Coastguard Worker   EXPECT_NE(P, nullptr);
202*76559068SAndroid Build Coastguard Worker   free(P);
203*76559068SAndroid Build Coastguard Worker   P = calloc(0U, 1U);
204*76559068SAndroid Build Coastguard Worker   EXPECT_NE(P, nullptr);
205*76559068SAndroid Build Coastguard Worker   free(P);
206*76559068SAndroid Build Coastguard Worker 
207*76559068SAndroid Build Coastguard Worker   errno = 0;
208*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(calloc(SIZE_MAX, 1U), nullptr);
209*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(errno, ENOMEM);
210*76559068SAndroid Build Coastguard Worker   errno = 0;
211*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(calloc(static_cast<size_t>(LONG_MAX) + 1U, 2U), nullptr);
212*76559068SAndroid Build Coastguard Worker   if (SCUDO_ANDROID)
213*76559068SAndroid Build Coastguard Worker     EXPECT_EQ(errno, ENOMEM);
214*76559068SAndroid Build Coastguard Worker   errno = 0;
215*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(calloc(SIZE_MAX, SIZE_MAX), nullptr);
216*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(errno, ENOMEM);
217*76559068SAndroid Build Coastguard Worker }
218*76559068SAndroid Build Coastguard Worker 
TEST_F(ScudoWrappersCTest,SmallAlign)219*76559068SAndroid Build Coastguard Worker TEST_F(ScudoWrappersCTest, SmallAlign) {
220*76559068SAndroid Build Coastguard Worker   // Allocating pointers by the powers of 2 from 1 to 0x10000
221*76559068SAndroid Build Coastguard Worker   // Using powers of 2 due to memalign using powers of 2 and test more sizes
222*76559068SAndroid Build Coastguard Worker   constexpr size_t MaxSize = 0x10000;
223*76559068SAndroid Build Coastguard Worker   std::vector<void *> ptrs;
224*76559068SAndroid Build Coastguard Worker   // Reserving space to prevent further allocation during the test
225*76559068SAndroid Build Coastguard Worker   ptrs.reserve((scudo::getLeastSignificantSetBitIndex(MaxSize) + 1) *
226*76559068SAndroid Build Coastguard Worker                (scudo::getLeastSignificantSetBitIndex(MaxSize) + 1) * 3);
227*76559068SAndroid Build Coastguard Worker   for (size_t Size = 1; Size <= MaxSize; Size <<= 1) {
228*76559068SAndroid Build Coastguard Worker     for (size_t Align = 1; Align <= MaxSize; Align <<= 1) {
229*76559068SAndroid Build Coastguard Worker       for (size_t Count = 0; Count < 3; ++Count) {
230*76559068SAndroid Build Coastguard Worker         void *P = memalign(Align, Size);
231*76559068SAndroid Build Coastguard Worker         EXPECT_TRUE(reinterpret_cast<uintptr_t>(P) % Align == 0);
232*76559068SAndroid Build Coastguard Worker         ptrs.push_back(P);
233*76559068SAndroid Build Coastguard Worker       }
234*76559068SAndroid Build Coastguard Worker     }
235*76559068SAndroid Build Coastguard Worker   }
236*76559068SAndroid Build Coastguard Worker   for (void *ptr : ptrs)
237*76559068SAndroid Build Coastguard Worker     free(ptr);
238*76559068SAndroid Build Coastguard Worker }
239*76559068SAndroid Build Coastguard Worker 
TEST_F(ScudoWrappersCTest,Memalign)240*76559068SAndroid Build Coastguard Worker TEST_F(ScudoWrappersCTest, Memalign) {
241*76559068SAndroid Build Coastguard Worker   void *P;
242*76559068SAndroid Build Coastguard Worker   for (size_t I = FIRST_32_SECOND_64(2U, 3U); I <= 18U; I++) {
243*76559068SAndroid Build Coastguard Worker     const size_t Alignment = 1U << I;
244*76559068SAndroid Build Coastguard Worker 
245*76559068SAndroid Build Coastguard Worker     P = memalign(Alignment, Size);
246*76559068SAndroid Build Coastguard Worker     EXPECT_NE(P, nullptr);
247*76559068SAndroid Build Coastguard Worker     EXPECT_LE(Size, malloc_usable_size(P));
248*76559068SAndroid Build Coastguard Worker     EXPECT_EQ(reinterpret_cast<uintptr_t>(P) % Alignment, 0U);
249*76559068SAndroid Build Coastguard Worker     verifyAllocHookPtr(P);
250*76559068SAndroid Build Coastguard Worker     verifyAllocHookSize(Size);
251*76559068SAndroid Build Coastguard Worker     free(P);
252*76559068SAndroid Build Coastguard Worker     verifyDeallocHookPtr(P);
253*76559068SAndroid Build Coastguard Worker 
254*76559068SAndroid Build Coastguard Worker     P = nullptr;
255*76559068SAndroid Build Coastguard Worker     EXPECT_EQ(posix_memalign(&P, Alignment, Size), 0);
256*76559068SAndroid Build Coastguard Worker     EXPECT_NE(P, nullptr);
257*76559068SAndroid Build Coastguard Worker     EXPECT_LE(Size, malloc_usable_size(P));
258*76559068SAndroid Build Coastguard Worker     EXPECT_EQ(reinterpret_cast<uintptr_t>(P) % Alignment, 0U);
259*76559068SAndroid Build Coastguard Worker     verifyAllocHookPtr(P);
260*76559068SAndroid Build Coastguard Worker     verifyAllocHookSize(Size);
261*76559068SAndroid Build Coastguard Worker     free(P);
262*76559068SAndroid Build Coastguard Worker     verifyDeallocHookPtr(P);
263*76559068SAndroid Build Coastguard Worker   }
264*76559068SAndroid Build Coastguard Worker 
265*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(memalign(4096U, SIZE_MAX), nullptr);
266*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(posix_memalign(&P, 15U, Size), EINVAL);
267*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(posix_memalign(&P, 4096U, SIZE_MAX), ENOMEM);
268*76559068SAndroid Build Coastguard Worker 
269*76559068SAndroid Build Coastguard Worker   // Android's memalign accepts non power-of-2 alignments, and 0.
270*76559068SAndroid Build Coastguard Worker   if (SCUDO_ANDROID) {
271*76559068SAndroid Build Coastguard Worker     for (size_t Alignment = 0U; Alignment <= 128U; Alignment++) {
272*76559068SAndroid Build Coastguard Worker       P = memalign(Alignment, 1024U);
273*76559068SAndroid Build Coastguard Worker       EXPECT_NE(P, nullptr);
274*76559068SAndroid Build Coastguard Worker       verifyAllocHookPtr(P);
275*76559068SAndroid Build Coastguard Worker       verifyAllocHookSize(Size);
276*76559068SAndroid Build Coastguard Worker       free(P);
277*76559068SAndroid Build Coastguard Worker       verifyDeallocHookPtr(P);
278*76559068SAndroid Build Coastguard Worker     }
279*76559068SAndroid Build Coastguard Worker   }
280*76559068SAndroid Build Coastguard Worker }
281*76559068SAndroid Build Coastguard Worker 
TEST_F(ScudoWrappersCTest,AlignedAlloc)282*76559068SAndroid Build Coastguard Worker TEST_F(ScudoWrappersCTest, AlignedAlloc) {
283*76559068SAndroid Build Coastguard Worker   const size_t Alignment = 4096U;
284*76559068SAndroid Build Coastguard Worker   void *P = aligned_alloc(Alignment, Alignment * 4U);
285*76559068SAndroid Build Coastguard Worker   EXPECT_NE(P, nullptr);
286*76559068SAndroid Build Coastguard Worker   EXPECT_LE(Alignment * 4U, malloc_usable_size(P));
287*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(reinterpret_cast<uintptr_t>(P) % Alignment, 0U);
288*76559068SAndroid Build Coastguard Worker   verifyAllocHookPtr(P);
289*76559068SAndroid Build Coastguard Worker   verifyAllocHookSize(Alignment * 4U);
290*76559068SAndroid Build Coastguard Worker   free(P);
291*76559068SAndroid Build Coastguard Worker   verifyDeallocHookPtr(P);
292*76559068SAndroid Build Coastguard Worker 
293*76559068SAndroid Build Coastguard Worker   errno = 0;
294*76559068SAndroid Build Coastguard Worker   P = aligned_alloc(Alignment, Size);
295*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(P, nullptr);
296*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(errno, EINVAL);
297*76559068SAndroid Build Coastguard Worker }
298*76559068SAndroid Build Coastguard Worker 
TEST_F(ScudoWrappersCDeathTest,Realloc)299*76559068SAndroid Build Coastguard Worker TEST_F(ScudoWrappersCDeathTest, Realloc) {
300*76559068SAndroid Build Coastguard Worker   invalidateHookPtrs();
301*76559068SAndroid Build Coastguard Worker   // realloc(nullptr, N) is malloc(N)
302*76559068SAndroid Build Coastguard Worker   void *P = realloc(nullptr, Size);
303*76559068SAndroid Build Coastguard Worker   EXPECT_NE(P, nullptr);
304*76559068SAndroid Build Coastguard Worker   verifyAllocHookPtr(P);
305*76559068SAndroid Build Coastguard Worker   verifyAllocHookSize(Size);
306*76559068SAndroid Build Coastguard Worker   free(P);
307*76559068SAndroid Build Coastguard Worker   verifyDeallocHookPtr(P);
308*76559068SAndroid Build Coastguard Worker 
309*76559068SAndroid Build Coastguard Worker   invalidateHookPtrs();
310*76559068SAndroid Build Coastguard Worker   P = malloc(Size);
311*76559068SAndroid Build Coastguard Worker   EXPECT_NE(P, nullptr);
312*76559068SAndroid Build Coastguard Worker   // realloc(P, 0U) is free(P) and returns nullptr
313*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(realloc(P, 0U), nullptr);
314*76559068SAndroid Build Coastguard Worker   verifyDeallocHookPtr(P);
315*76559068SAndroid Build Coastguard Worker 
316*76559068SAndroid Build Coastguard Worker   P = malloc(Size);
317*76559068SAndroid Build Coastguard Worker   EXPECT_NE(P, nullptr);
318*76559068SAndroid Build Coastguard Worker   EXPECT_LE(Size, malloc_usable_size(P));
319*76559068SAndroid Build Coastguard Worker   memset(P, 0x42, Size);
320*76559068SAndroid Build Coastguard Worker 
321*76559068SAndroid Build Coastguard Worker   invalidateHookPtrs();
322*76559068SAndroid Build Coastguard Worker   void *OldP = P;
323*76559068SAndroid Build Coastguard Worker   P = realloc(P, Size * 2U);
324*76559068SAndroid Build Coastguard Worker   EXPECT_NE(P, nullptr);
325*76559068SAndroid Build Coastguard Worker   EXPECT_LE(Size * 2U, malloc_usable_size(P));
326*76559068SAndroid Build Coastguard Worker   for (size_t I = 0; I < Size; I++)
327*76559068SAndroid Build Coastguard Worker     EXPECT_EQ(0x42, (reinterpret_cast<uint8_t *>(P))[I]);
328*76559068SAndroid Build Coastguard Worker   if (OldP == P) {
329*76559068SAndroid Build Coastguard Worker     verifyDeallocHookPtr(OldP);
330*76559068SAndroid Build Coastguard Worker     verifyAllocHookPtr(OldP);
331*76559068SAndroid Build Coastguard Worker   } else {
332*76559068SAndroid Build Coastguard Worker     verifyAllocHookPtr(P);
333*76559068SAndroid Build Coastguard Worker     verifyAllocHookSize(Size * 2U);
334*76559068SAndroid Build Coastguard Worker     verifyDeallocHookPtr(OldP);
335*76559068SAndroid Build Coastguard Worker   }
336*76559068SAndroid Build Coastguard Worker   verifyReallocHookPtrs(OldP, P, Size * 2U);
337*76559068SAndroid Build Coastguard Worker 
338*76559068SAndroid Build Coastguard Worker   invalidateHookPtrs();
339*76559068SAndroid Build Coastguard Worker   OldP = P;
340*76559068SAndroid Build Coastguard Worker   P = realloc(P, Size / 2U);
341*76559068SAndroid Build Coastguard Worker   EXPECT_NE(P, nullptr);
342*76559068SAndroid Build Coastguard Worker   EXPECT_LE(Size / 2U, malloc_usable_size(P));
343*76559068SAndroid Build Coastguard Worker   for (size_t I = 0; I < Size / 2U; I++)
344*76559068SAndroid Build Coastguard Worker     EXPECT_EQ(0x42, (reinterpret_cast<uint8_t *>(P))[I]);
345*76559068SAndroid Build Coastguard Worker   if (OldP == P) {
346*76559068SAndroid Build Coastguard Worker     verifyDeallocHookPtr(OldP);
347*76559068SAndroid Build Coastguard Worker     verifyAllocHookPtr(OldP);
348*76559068SAndroid Build Coastguard Worker   } else {
349*76559068SAndroid Build Coastguard Worker     verifyAllocHookPtr(P);
350*76559068SAndroid Build Coastguard Worker     verifyAllocHookSize(Size / 2U);
351*76559068SAndroid Build Coastguard Worker   }
352*76559068SAndroid Build Coastguard Worker   verifyReallocHookPtrs(OldP, P, Size / 2U);
353*76559068SAndroid Build Coastguard Worker   free(P);
354*76559068SAndroid Build Coastguard Worker 
355*76559068SAndroid Build Coastguard Worker   EXPECT_DEATH(P = realloc(P, Size), "");
356*76559068SAndroid Build Coastguard Worker 
357*76559068SAndroid Build Coastguard Worker   errno = 0;
358*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(realloc(nullptr, SIZE_MAX), nullptr);
359*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(errno, ENOMEM);
360*76559068SAndroid Build Coastguard Worker   P = malloc(Size);
361*76559068SAndroid Build Coastguard Worker   EXPECT_NE(P, nullptr);
362*76559068SAndroid Build Coastguard Worker   errno = 0;
363*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(realloc(P, SIZE_MAX), nullptr);
364*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(errno, ENOMEM);
365*76559068SAndroid Build Coastguard Worker   free(P);
366*76559068SAndroid Build Coastguard Worker 
367*76559068SAndroid Build Coastguard Worker   // Android allows realloc of memalign pointers.
368*76559068SAndroid Build Coastguard Worker   if (SCUDO_ANDROID) {
369*76559068SAndroid Build Coastguard Worker     const size_t Alignment = 1024U;
370*76559068SAndroid Build Coastguard Worker     P = memalign(Alignment, Size);
371*76559068SAndroid Build Coastguard Worker     EXPECT_NE(P, nullptr);
372*76559068SAndroid Build Coastguard Worker     EXPECT_LE(Size, malloc_usable_size(P));
373*76559068SAndroid Build Coastguard Worker     EXPECT_EQ(reinterpret_cast<uintptr_t>(P) % Alignment, 0U);
374*76559068SAndroid Build Coastguard Worker     memset(P, 0x42, Size);
375*76559068SAndroid Build Coastguard Worker 
376*76559068SAndroid Build Coastguard Worker     P = realloc(P, Size * 2U);
377*76559068SAndroid Build Coastguard Worker     EXPECT_NE(P, nullptr);
378*76559068SAndroid Build Coastguard Worker     EXPECT_LE(Size * 2U, malloc_usable_size(P));
379*76559068SAndroid Build Coastguard Worker     for (size_t I = 0; I < Size; I++)
380*76559068SAndroid Build Coastguard Worker       EXPECT_EQ(0x42, (reinterpret_cast<uint8_t *>(P))[I]);
381*76559068SAndroid Build Coastguard Worker     free(P);
382*76559068SAndroid Build Coastguard Worker   }
383*76559068SAndroid Build Coastguard Worker }
384*76559068SAndroid Build Coastguard Worker 
385*76559068SAndroid Build Coastguard Worker #if !SCUDO_FUCHSIA
TEST_F(ScudoWrappersCTest,MallOpt)386*76559068SAndroid Build Coastguard Worker TEST_F(ScudoWrappersCTest, MallOpt) {
387*76559068SAndroid Build Coastguard Worker   errno = 0;
388*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(mallopt(-1000, 1), 0);
389*76559068SAndroid Build Coastguard Worker   // mallopt doesn't set errno.
390*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(errno, 0);
391*76559068SAndroid Build Coastguard Worker 
392*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(mallopt(M_PURGE, 0), 1);
393*76559068SAndroid Build Coastguard Worker 
394*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(mallopt(M_DECAY_TIME, 1), 1);
395*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(mallopt(M_DECAY_TIME, 0), 1);
396*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(mallopt(M_DECAY_TIME, 1), 1);
397*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(mallopt(M_DECAY_TIME, 0), 1);
398*76559068SAndroid Build Coastguard Worker 
399*76559068SAndroid Build Coastguard Worker   if (SCUDO_ANDROID) {
400*76559068SAndroid Build Coastguard Worker     EXPECT_EQ(mallopt(M_CACHE_COUNT_MAX, 100), 1);
401*76559068SAndroid Build Coastguard Worker     EXPECT_EQ(mallopt(M_CACHE_SIZE_MAX, 1024 * 1024 * 2), 1);
402*76559068SAndroid Build Coastguard Worker     EXPECT_EQ(mallopt(M_TSDS_COUNT_MAX, 10), 1);
403*76559068SAndroid Build Coastguard Worker   }
404*76559068SAndroid Build Coastguard Worker }
405*76559068SAndroid Build Coastguard Worker #endif
406*76559068SAndroid Build Coastguard Worker 
TEST_F(ScudoWrappersCTest,OtherAlloc)407*76559068SAndroid Build Coastguard Worker TEST_F(ScudoWrappersCTest, OtherAlloc) {
408*76559068SAndroid Build Coastguard Worker #if HAVE_PVALLOC
409*76559068SAndroid Build Coastguard Worker   const size_t PageSize = static_cast<size_t>(sysconf(_SC_PAGESIZE));
410*76559068SAndroid Build Coastguard Worker 
411*76559068SAndroid Build Coastguard Worker   void *P = pvalloc(Size);
412*76559068SAndroid Build Coastguard Worker   EXPECT_NE(P, nullptr);
413*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(reinterpret_cast<uintptr_t>(P) & (PageSize - 1), 0U);
414*76559068SAndroid Build Coastguard Worker   EXPECT_LE(PageSize, malloc_usable_size(P));
415*76559068SAndroid Build Coastguard Worker   verifyAllocHookPtr(P);
416*76559068SAndroid Build Coastguard Worker   // Size will be rounded up to PageSize.
417*76559068SAndroid Build Coastguard Worker   verifyAllocHookSize(PageSize);
418*76559068SAndroid Build Coastguard Worker   free(P);
419*76559068SAndroid Build Coastguard Worker   verifyDeallocHookPtr(P);
420*76559068SAndroid Build Coastguard Worker 
421*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(pvalloc(SIZE_MAX), nullptr);
422*76559068SAndroid Build Coastguard Worker 
423*76559068SAndroid Build Coastguard Worker   P = pvalloc(Size);
424*76559068SAndroid Build Coastguard Worker   EXPECT_NE(P, nullptr);
425*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(reinterpret_cast<uintptr_t>(P) & (PageSize - 1), 0U);
426*76559068SAndroid Build Coastguard Worker   free(P);
427*76559068SAndroid Build Coastguard Worker #endif
428*76559068SAndroid Build Coastguard Worker 
429*76559068SAndroid Build Coastguard Worker #if HAVE_VALLOC
430*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(valloc(SIZE_MAX), nullptr);
431*76559068SAndroid Build Coastguard Worker #endif
432*76559068SAndroid Build Coastguard Worker }
433*76559068SAndroid Build Coastguard Worker 
434*76559068SAndroid Build Coastguard Worker template<typename FieldType>
MallInfoTest()435*76559068SAndroid Build Coastguard Worker void MallInfoTest() {
436*76559068SAndroid Build Coastguard Worker   // mallinfo is deprecated.
437*76559068SAndroid Build Coastguard Worker #pragma clang diagnostic push
438*76559068SAndroid Build Coastguard Worker #pragma clang diagnostic ignored "-Wdeprecated-declarations"
439*76559068SAndroid Build Coastguard Worker   const FieldType BypassQuarantineSize = 1024U;
440*76559068SAndroid Build Coastguard Worker   struct mallinfo MI = mallinfo();
441*76559068SAndroid Build Coastguard Worker   FieldType Allocated = MI.uordblks;
442*76559068SAndroid Build Coastguard Worker   void *P = malloc(BypassQuarantineSize);
443*76559068SAndroid Build Coastguard Worker   EXPECT_NE(P, nullptr);
444*76559068SAndroid Build Coastguard Worker   MI = mallinfo();
445*76559068SAndroid Build Coastguard Worker   EXPECT_GE(MI.uordblks, Allocated + BypassQuarantineSize);
446*76559068SAndroid Build Coastguard Worker   EXPECT_GT(MI.hblkhd, static_cast<FieldType>(0));
447*76559068SAndroid Build Coastguard Worker   FieldType Free = MI.fordblks;
448*76559068SAndroid Build Coastguard Worker   free(P);
449*76559068SAndroid Build Coastguard Worker   MI = mallinfo();
450*76559068SAndroid Build Coastguard Worker   EXPECT_GE(MI.fordblks, Free + BypassQuarantineSize);
451*76559068SAndroid Build Coastguard Worker #pragma clang diagnostic pop
452*76559068SAndroid Build Coastguard Worker }
453*76559068SAndroid Build Coastguard Worker 
454*76559068SAndroid Build Coastguard Worker #if !SCUDO_FUCHSIA
TEST_F(ScudoWrappersCTest,MallInfo)455*76559068SAndroid Build Coastguard Worker TEST_F(ScudoWrappersCTest, MallInfo) {
456*76559068SAndroid Build Coastguard Worker #if SCUDO_ANDROID
457*76559068SAndroid Build Coastguard Worker   // Android accidentally set the fields to size_t instead of int.
458*76559068SAndroid Build Coastguard Worker   MallInfoTest<size_t>();
459*76559068SAndroid Build Coastguard Worker #else
460*76559068SAndroid Build Coastguard Worker   MallInfoTest<int>();
461*76559068SAndroid Build Coastguard Worker #endif
462*76559068SAndroid Build Coastguard Worker }
463*76559068SAndroid Build Coastguard Worker #endif
464*76559068SAndroid Build Coastguard Worker 
465*76559068SAndroid Build Coastguard Worker #if __GLIBC_PREREQ(2, 33) || SCUDO_ANDROID
TEST_F(ScudoWrappersCTest,MallInfo2)466*76559068SAndroid Build Coastguard Worker TEST_F(ScudoWrappersCTest, MallInfo2) {
467*76559068SAndroid Build Coastguard Worker   const size_t BypassQuarantineSize = 1024U;
468*76559068SAndroid Build Coastguard Worker   struct mallinfo2 MI = mallinfo2();
469*76559068SAndroid Build Coastguard Worker   size_t Allocated = MI.uordblks;
470*76559068SAndroid Build Coastguard Worker   void *P = malloc(BypassQuarantineSize);
471*76559068SAndroid Build Coastguard Worker   EXPECT_NE(P, nullptr);
472*76559068SAndroid Build Coastguard Worker   MI = mallinfo2();
473*76559068SAndroid Build Coastguard Worker   EXPECT_GE(MI.uordblks, Allocated + BypassQuarantineSize);
474*76559068SAndroid Build Coastguard Worker   EXPECT_GT(MI.hblkhd, 0U);
475*76559068SAndroid Build Coastguard Worker   size_t Free = MI.fordblks;
476*76559068SAndroid Build Coastguard Worker   free(P);
477*76559068SAndroid Build Coastguard Worker   MI = mallinfo2();
478*76559068SAndroid Build Coastguard Worker   EXPECT_GE(MI.fordblks, Free + BypassQuarantineSize);
479*76559068SAndroid Build Coastguard Worker }
480*76559068SAndroid Build Coastguard Worker #endif
481*76559068SAndroid Build Coastguard Worker 
482*76559068SAndroid Build Coastguard Worker static uintptr_t BoundaryP;
483*76559068SAndroid Build Coastguard Worker static size_t Count;
484*76559068SAndroid Build Coastguard Worker 
callback(uintptr_t Base,UNUSED size_t Size,UNUSED void * Arg)485*76559068SAndroid Build Coastguard Worker static void callback(uintptr_t Base, UNUSED size_t Size, UNUSED void *Arg) {
486*76559068SAndroid Build Coastguard Worker   if (scudo::archSupportsMemoryTagging()) {
487*76559068SAndroid Build Coastguard Worker     Base = scudo::untagPointer(Base);
488*76559068SAndroid Build Coastguard Worker     BoundaryP = scudo::untagPointer(BoundaryP);
489*76559068SAndroid Build Coastguard Worker   }
490*76559068SAndroid Build Coastguard Worker   if (Base == BoundaryP)
491*76559068SAndroid Build Coastguard Worker     Count++;
492*76559068SAndroid Build Coastguard Worker }
493*76559068SAndroid Build Coastguard Worker 
494*76559068SAndroid Build Coastguard Worker // Verify that a block located on an iteration boundary is not mis-accounted.
495*76559068SAndroid Build Coastguard Worker // To achieve this, we allocate a chunk for which the backing block will be
496*76559068SAndroid Build Coastguard Worker // aligned on a page, then run the malloc_iterate on both the pages that the
497*76559068SAndroid Build Coastguard Worker // block is a boundary for. It must only be seen once by the callback function.
TEST_F(ScudoWrappersCTest,MallocIterateBoundary)498*76559068SAndroid Build Coastguard Worker TEST_F(ScudoWrappersCTest, MallocIterateBoundary) {
499*76559068SAndroid Build Coastguard Worker   const size_t PageSize = static_cast<size_t>(sysconf(_SC_PAGESIZE));
500*76559068SAndroid Build Coastguard Worker #if SCUDO_ANDROID
501*76559068SAndroid Build Coastguard Worker   // Android uses a 16 byte alignment for both 32 bit and 64 bit.
502*76559068SAndroid Build Coastguard Worker   const size_t BlockDelta = 16U;
503*76559068SAndroid Build Coastguard Worker #else
504*76559068SAndroid Build Coastguard Worker   const size_t BlockDelta = FIRST_32_SECOND_64(8U, 16U);
505*76559068SAndroid Build Coastguard Worker #endif
506*76559068SAndroid Build Coastguard Worker   const size_t SpecialSize = PageSize - BlockDelta;
507*76559068SAndroid Build Coastguard Worker 
508*76559068SAndroid Build Coastguard Worker   // We aren't guaranteed that any size class is exactly a page wide. So we need
509*76559068SAndroid Build Coastguard Worker   // to keep making allocations until we get an allocation that starts exactly
510*76559068SAndroid Build Coastguard Worker   // on a page boundary. The BlockDelta value is expected to be the number of
511*76559068SAndroid Build Coastguard Worker   // bytes to subtract from a returned pointer to get to the actual start of
512*76559068SAndroid Build Coastguard Worker   // the pointer in the size class. In practice, this means BlockDelta should
513*76559068SAndroid Build Coastguard Worker   // be set to the minimum alignment in bytes for the allocation.
514*76559068SAndroid Build Coastguard Worker   //
515*76559068SAndroid Build Coastguard Worker   // With a 16-byte block alignment and 4096-byte page size, each allocation has
516*76559068SAndroid Build Coastguard Worker   // a probability of (1 - (16/4096)) of failing to meet the alignment
517*76559068SAndroid Build Coastguard Worker   // requirements, and the probability of failing 65536 times is
518*76559068SAndroid Build Coastguard Worker   // (1 - (16/4096))^65536 < 10^-112. So if we still haven't succeeded after
519*76559068SAndroid Build Coastguard Worker   // 65536 tries, give up.
520*76559068SAndroid Build Coastguard Worker   uintptr_t Block;
521*76559068SAndroid Build Coastguard Worker   void *P = nullptr;
522*76559068SAndroid Build Coastguard Worker   for (unsigned I = 0; I != 65536; ++I) {
523*76559068SAndroid Build Coastguard Worker     void *PrevP = P;
524*76559068SAndroid Build Coastguard Worker     P = malloc(SpecialSize);
525*76559068SAndroid Build Coastguard Worker     EXPECT_NE(P, nullptr);
526*76559068SAndroid Build Coastguard Worker     *reinterpret_cast<void **>(P) = PrevP;
527*76559068SAndroid Build Coastguard Worker     BoundaryP = reinterpret_cast<uintptr_t>(P);
528*76559068SAndroid Build Coastguard Worker     Block = BoundaryP - BlockDelta;
529*76559068SAndroid Build Coastguard Worker     if ((Block & (PageSize - 1)) == 0U)
530*76559068SAndroid Build Coastguard Worker       break;
531*76559068SAndroid Build Coastguard Worker   }
532*76559068SAndroid Build Coastguard Worker   EXPECT_EQ((Block & (PageSize - 1)), 0U);
533*76559068SAndroid Build Coastguard Worker 
534*76559068SAndroid Build Coastguard Worker   Count = 0U;
535*76559068SAndroid Build Coastguard Worker   malloc_disable();
536*76559068SAndroid Build Coastguard Worker   malloc_iterate(Block - PageSize, PageSize, callback, nullptr);
537*76559068SAndroid Build Coastguard Worker   malloc_iterate(Block, PageSize, callback, nullptr);
538*76559068SAndroid Build Coastguard Worker   malloc_enable();
539*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(Count, 1U);
540*76559068SAndroid Build Coastguard Worker 
541*76559068SAndroid Build Coastguard Worker   while (P) {
542*76559068SAndroid Build Coastguard Worker     void *NextP = *reinterpret_cast<void **>(P);
543*76559068SAndroid Build Coastguard Worker     free(P);
544*76559068SAndroid Build Coastguard Worker     P = NextP;
545*76559068SAndroid Build Coastguard Worker   }
546*76559068SAndroid Build Coastguard Worker }
547*76559068SAndroid Build Coastguard Worker 
548*76559068SAndroid Build Coastguard Worker // Fuchsia doesn't have alarm, fork or malloc_info.
549*76559068SAndroid Build Coastguard Worker #if !SCUDO_FUCHSIA
TEST_F(ScudoWrappersCDeathTest,MallocDisableDeadlock)550*76559068SAndroid Build Coastguard Worker TEST_F(ScudoWrappersCDeathTest, MallocDisableDeadlock) {
551*76559068SAndroid Build Coastguard Worker   // We expect heap operations within a disable/enable scope to deadlock.
552*76559068SAndroid Build Coastguard Worker   EXPECT_DEATH(
553*76559068SAndroid Build Coastguard Worker       {
554*76559068SAndroid Build Coastguard Worker         void *P = malloc(Size);
555*76559068SAndroid Build Coastguard Worker         EXPECT_NE(P, nullptr);
556*76559068SAndroid Build Coastguard Worker         free(P);
557*76559068SAndroid Build Coastguard Worker         malloc_disable();
558*76559068SAndroid Build Coastguard Worker         alarm(1);
559*76559068SAndroid Build Coastguard Worker         P = malloc(Size);
560*76559068SAndroid Build Coastguard Worker         malloc_enable();
561*76559068SAndroid Build Coastguard Worker       },
562*76559068SAndroid Build Coastguard Worker       "");
563*76559068SAndroid Build Coastguard Worker }
564*76559068SAndroid Build Coastguard Worker 
TEST_F(ScudoWrappersCTest,MallocInfo)565*76559068SAndroid Build Coastguard Worker TEST_F(ScudoWrappersCTest, MallocInfo) {
566*76559068SAndroid Build Coastguard Worker   // Use volatile so that the allocations don't get optimized away.
567*76559068SAndroid Build Coastguard Worker   void *volatile P1 = malloc(1234);
568*76559068SAndroid Build Coastguard Worker   void *volatile P2 = malloc(4321);
569*76559068SAndroid Build Coastguard Worker 
570*76559068SAndroid Build Coastguard Worker   char Buffer[16384];
571*76559068SAndroid Build Coastguard Worker   FILE *F = fmemopen(Buffer, sizeof(Buffer), "w+");
572*76559068SAndroid Build Coastguard Worker   EXPECT_NE(F, nullptr);
573*76559068SAndroid Build Coastguard Worker   errno = 0;
574*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(malloc_info(0, F), 0);
575*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(errno, 0);
576*76559068SAndroid Build Coastguard Worker   fclose(F);
577*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(strncmp(Buffer, "<malloc version=\"scudo-", 23), 0);
578*76559068SAndroid Build Coastguard Worker   EXPECT_NE(nullptr, strstr(Buffer, "<alloc size=\"1234\" count=\""));
579*76559068SAndroid Build Coastguard Worker   EXPECT_NE(nullptr, strstr(Buffer, "<alloc size=\"4321\" count=\""));
580*76559068SAndroid Build Coastguard Worker 
581*76559068SAndroid Build Coastguard Worker   free(P1);
582*76559068SAndroid Build Coastguard Worker   free(P2);
583*76559068SAndroid Build Coastguard Worker }
584*76559068SAndroid Build Coastguard Worker 
TEST_F(ScudoWrappersCDeathTest,Fork)585*76559068SAndroid Build Coastguard Worker TEST_F(ScudoWrappersCDeathTest, Fork) {
586*76559068SAndroid Build Coastguard Worker   void *P;
587*76559068SAndroid Build Coastguard Worker   pid_t Pid = fork();
588*76559068SAndroid Build Coastguard Worker   EXPECT_GE(Pid, 0) << strerror(errno);
589*76559068SAndroid Build Coastguard Worker   if (Pid == 0) {
590*76559068SAndroid Build Coastguard Worker     P = malloc(Size);
591*76559068SAndroid Build Coastguard Worker     EXPECT_NE(P, nullptr);
592*76559068SAndroid Build Coastguard Worker     memset(P, 0x42, Size);
593*76559068SAndroid Build Coastguard Worker     free(P);
594*76559068SAndroid Build Coastguard Worker     _exit(0);
595*76559068SAndroid Build Coastguard Worker   }
596*76559068SAndroid Build Coastguard Worker   waitpid(Pid, nullptr, 0);
597*76559068SAndroid Build Coastguard Worker   P = malloc(Size);
598*76559068SAndroid Build Coastguard Worker   EXPECT_NE(P, nullptr);
599*76559068SAndroid Build Coastguard Worker   memset(P, 0x42, Size);
600*76559068SAndroid Build Coastguard Worker   free(P);
601*76559068SAndroid Build Coastguard Worker 
602*76559068SAndroid Build Coastguard Worker   // fork should stall if the allocator has been disabled.
603*76559068SAndroid Build Coastguard Worker   EXPECT_DEATH(
604*76559068SAndroid Build Coastguard Worker       {
605*76559068SAndroid Build Coastguard Worker         malloc_disable();
606*76559068SAndroid Build Coastguard Worker         alarm(1);
607*76559068SAndroid Build Coastguard Worker         Pid = fork();
608*76559068SAndroid Build Coastguard Worker         EXPECT_GE(Pid, 0);
609*76559068SAndroid Build Coastguard Worker       },
610*76559068SAndroid Build Coastguard Worker       "");
611*76559068SAndroid Build Coastguard Worker }
612*76559068SAndroid Build Coastguard Worker 
613*76559068SAndroid Build Coastguard Worker static pthread_mutex_t Mutex;
614*76559068SAndroid Build Coastguard Worker static pthread_cond_t Conditional = PTHREAD_COND_INITIALIZER;
615*76559068SAndroid Build Coastguard Worker static bool Ready;
616*76559068SAndroid Build Coastguard Worker 
enableMalloc(UNUSED void * Unused)617*76559068SAndroid Build Coastguard Worker static void *enableMalloc(UNUSED void *Unused) {
618*76559068SAndroid Build Coastguard Worker   // Initialize the allocator for this thread.
619*76559068SAndroid Build Coastguard Worker   void *P = malloc(Size);
620*76559068SAndroid Build Coastguard Worker   EXPECT_NE(P, nullptr);
621*76559068SAndroid Build Coastguard Worker   memset(P, 0x42, Size);
622*76559068SAndroid Build Coastguard Worker   free(P);
623*76559068SAndroid Build Coastguard Worker 
624*76559068SAndroid Build Coastguard Worker   // Signal the main thread we are ready.
625*76559068SAndroid Build Coastguard Worker   pthread_mutex_lock(&Mutex);
626*76559068SAndroid Build Coastguard Worker   Ready = true;
627*76559068SAndroid Build Coastguard Worker   pthread_cond_signal(&Conditional);
628*76559068SAndroid Build Coastguard Worker   pthread_mutex_unlock(&Mutex);
629*76559068SAndroid Build Coastguard Worker 
630*76559068SAndroid Build Coastguard Worker   // Wait for the malloc_disable & fork, then enable the allocator again.
631*76559068SAndroid Build Coastguard Worker   sleep(1);
632*76559068SAndroid Build Coastguard Worker   malloc_enable();
633*76559068SAndroid Build Coastguard Worker 
634*76559068SAndroid Build Coastguard Worker   return nullptr;
635*76559068SAndroid Build Coastguard Worker }
636*76559068SAndroid Build Coastguard Worker 
TEST_F(ScudoWrappersCTest,DisableForkEnable)637*76559068SAndroid Build Coastguard Worker TEST_F(ScudoWrappersCTest, DisableForkEnable) {
638*76559068SAndroid Build Coastguard Worker   pthread_t ThreadId;
639*76559068SAndroid Build Coastguard Worker   Ready = false;
640*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(pthread_create(&ThreadId, nullptr, &enableMalloc, nullptr), 0);
641*76559068SAndroid Build Coastguard Worker 
642*76559068SAndroid Build Coastguard Worker   // Wait for the thread to be warmed up.
643*76559068SAndroid Build Coastguard Worker   pthread_mutex_lock(&Mutex);
644*76559068SAndroid Build Coastguard Worker   while (!Ready)
645*76559068SAndroid Build Coastguard Worker     pthread_cond_wait(&Conditional, &Mutex);
646*76559068SAndroid Build Coastguard Worker   pthread_mutex_unlock(&Mutex);
647*76559068SAndroid Build Coastguard Worker 
648*76559068SAndroid Build Coastguard Worker   // Disable the allocator and fork. fork should succeed after malloc_enable.
649*76559068SAndroid Build Coastguard Worker   malloc_disable();
650*76559068SAndroid Build Coastguard Worker   pid_t Pid = fork();
651*76559068SAndroid Build Coastguard Worker   EXPECT_GE(Pid, 0);
652*76559068SAndroid Build Coastguard Worker   if (Pid == 0) {
653*76559068SAndroid Build Coastguard Worker     void *P = malloc(Size);
654*76559068SAndroid Build Coastguard Worker     EXPECT_NE(P, nullptr);
655*76559068SAndroid Build Coastguard Worker     memset(P, 0x42, Size);
656*76559068SAndroid Build Coastguard Worker     free(P);
657*76559068SAndroid Build Coastguard Worker     _exit(0);
658*76559068SAndroid Build Coastguard Worker   }
659*76559068SAndroid Build Coastguard Worker   waitpid(Pid, nullptr, 0);
660*76559068SAndroid Build Coastguard Worker   EXPECT_EQ(pthread_join(ThreadId, 0), 0);
661*76559068SAndroid Build Coastguard Worker }
662*76559068SAndroid Build Coastguard Worker 
663*76559068SAndroid Build Coastguard Worker #endif // SCUDO_FUCHSIA
664