xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/msan/msan_allocator.cpp (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
168d75effSDimitry Andric //===-- msan_allocator.cpp -------------------------- ---------------------===//
268d75effSDimitry Andric //
368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
668d75effSDimitry Andric //
768d75effSDimitry Andric //===----------------------------------------------------------------------===//
868d75effSDimitry Andric //
968d75effSDimitry Andric // This file is a part of MemorySanitizer.
1068d75effSDimitry Andric //
1168d75effSDimitry Andric // MemorySanitizer allocator.
1268d75effSDimitry Andric //===----------------------------------------------------------------------===//
1368d75effSDimitry Andric 
1406c3fb27SDimitry Andric #include "msan_allocator.h"
1506c3fb27SDimitry Andric 
1606c3fb27SDimitry Andric #include "msan.h"
1706c3fb27SDimitry Andric #include "msan_interface_internal.h"
1806c3fb27SDimitry Andric #include "msan_origin.h"
1906c3fb27SDimitry Andric #include "msan_poisoning.h"
2006c3fb27SDimitry Andric #include "msan_thread.h"
2168d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator.h"
2268d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator_checks.h"
2368d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator_interface.h"
2468d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator_report.h"
2568d75effSDimitry Andric #include "sanitizer_common/sanitizer_errno.h"
2668d75effSDimitry Andric 
2768d75effSDimitry Andric namespace __msan {
2868d75effSDimitry Andric 
2968d75effSDimitry Andric struct Metadata {
3068d75effSDimitry Andric   uptr requested_size;
3168d75effSDimitry Andric };
3268d75effSDimitry Andric 
3368d75effSDimitry Andric struct MsanMapUnmapCallback {
3468d75effSDimitry Andric   void OnMap(uptr p, uptr size) const {}
3506c3fb27SDimitry Andric   void OnMapSecondary(uptr p, uptr size, uptr user_begin,
3606c3fb27SDimitry Andric                       uptr user_size) const {}
3768d75effSDimitry Andric   void OnUnmap(uptr p, uptr size) const {
3868d75effSDimitry Andric     __msan_unpoison((void *)p, size);
3968d75effSDimitry Andric 
4068d75effSDimitry Andric     // We are about to unmap a chunk of user memory.
4168d75effSDimitry Andric     // Mark the corresponding shadow memory as not needed.
4268d75effSDimitry Andric     uptr shadow_p = MEM_TO_SHADOW(p);
4368d75effSDimitry Andric     ReleaseMemoryPagesToOS(shadow_p, shadow_p + size);
4468d75effSDimitry Andric     if (__msan_get_track_origins()) {
4568d75effSDimitry Andric       uptr origin_p = MEM_TO_ORIGIN(p);
4668d75effSDimitry Andric       ReleaseMemoryPagesToOS(origin_p, origin_p + size);
4768d75effSDimitry Andric     }
4868d75effSDimitry Andric   }
4968d75effSDimitry Andric };
5068d75effSDimitry Andric 
5168d75effSDimitry Andric #if defined(__mips64)
5268d75effSDimitry Andric static const uptr kMaxAllowedMallocSize = 2UL << 30;
5368d75effSDimitry Andric 
5468d75effSDimitry Andric struct AP32 {
5568d75effSDimitry Andric   static const uptr kSpaceBeg = 0;
5668d75effSDimitry Andric   static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
5768d75effSDimitry Andric   static const uptr kMetadataSize = sizeof(Metadata);
5868d75effSDimitry Andric   typedef __sanitizer::CompactSizeClassMap SizeClassMap;
5968d75effSDimitry Andric   static const uptr kRegionSizeLog = 20;
6068d75effSDimitry Andric   using AddressSpaceView = LocalAddressSpaceView;
6168d75effSDimitry Andric   typedef MsanMapUnmapCallback MapUnmapCallback;
6268d75effSDimitry Andric   static const uptr kFlags = 0;
6368d75effSDimitry Andric };
6468d75effSDimitry Andric typedef SizeClassAllocator32<AP32> PrimaryAllocator;
6568d75effSDimitry Andric #elif defined(__x86_64__)
66bdd1243dSDimitry Andric #if SANITIZER_NETBSD || SANITIZER_LINUX
6768d75effSDimitry Andric static const uptr kAllocatorSpace = 0x700000000000ULL;
6868d75effSDimitry Andric #else
6968d75effSDimitry Andric static const uptr kAllocatorSpace = 0x600000000000ULL;
7068d75effSDimitry Andric #endif
7168d75effSDimitry Andric static const uptr kMaxAllowedMallocSize = 8UL << 30;
7268d75effSDimitry Andric 
7368d75effSDimitry Andric struct AP64 {  // Allocator64 parameters. Deliberately using a short name.
7468d75effSDimitry Andric   static const uptr kSpaceBeg = kAllocatorSpace;
7568d75effSDimitry Andric   static const uptr kSpaceSize = 0x40000000000;  // 4T.
7668d75effSDimitry Andric   static const uptr kMetadataSize = sizeof(Metadata);
7768d75effSDimitry Andric   typedef DefaultSizeClassMap SizeClassMap;
7868d75effSDimitry Andric   typedef MsanMapUnmapCallback MapUnmapCallback;
7968d75effSDimitry Andric   static const uptr kFlags = 0;
8068d75effSDimitry Andric   using AddressSpaceView = LocalAddressSpaceView;
8168d75effSDimitry Andric };
8268d75effSDimitry Andric 
8368d75effSDimitry Andric typedef SizeClassAllocator64<AP64> PrimaryAllocator;
8468d75effSDimitry Andric 
8506c3fb27SDimitry Andric #elif defined(__loongarch_lp64)
8606c3fb27SDimitry Andric const uptr kAllocatorSpace = 0x700000000000ULL;
8706c3fb27SDimitry Andric const uptr kMaxAllowedMallocSize = 8UL << 30;
8806c3fb27SDimitry Andric 
8906c3fb27SDimitry Andric struct AP64 {  // Allocator64 parameters. Deliberately using a short name.
9006c3fb27SDimitry Andric   static const uptr kSpaceBeg = kAllocatorSpace;
9106c3fb27SDimitry Andric   static const uptr kSpaceSize = 0x40000000000;  // 4T.
9206c3fb27SDimitry Andric   static const uptr kMetadataSize = sizeof(Metadata);
9306c3fb27SDimitry Andric   typedef DefaultSizeClassMap SizeClassMap;
9406c3fb27SDimitry Andric   typedef MsanMapUnmapCallback MapUnmapCallback;
9506c3fb27SDimitry Andric   static const uptr kFlags = 0;
9606c3fb27SDimitry Andric   using AddressSpaceView = LocalAddressSpaceView;
9706c3fb27SDimitry Andric };
9806c3fb27SDimitry Andric 
9906c3fb27SDimitry Andric typedef SizeClassAllocator64<AP64> PrimaryAllocator;
10006c3fb27SDimitry Andric 
10168d75effSDimitry Andric #elif defined(__powerpc64__)
10268d75effSDimitry Andric static const uptr kMaxAllowedMallocSize = 2UL << 30;  // 2G
10368d75effSDimitry Andric 
10468d75effSDimitry Andric struct AP64 {  // Allocator64 parameters. Deliberately using a short name.
10568d75effSDimitry Andric   static const uptr kSpaceBeg = 0x300000000000;
10668d75effSDimitry Andric   static const uptr kSpaceSize = 0x020000000000;  // 2T.
10768d75effSDimitry Andric   static const uptr kMetadataSize = sizeof(Metadata);
10868d75effSDimitry Andric   typedef DefaultSizeClassMap SizeClassMap;
10968d75effSDimitry Andric   typedef MsanMapUnmapCallback MapUnmapCallback;
11068d75effSDimitry Andric   static const uptr kFlags = 0;
11168d75effSDimitry Andric   using AddressSpaceView = LocalAddressSpaceView;
11268d75effSDimitry Andric };
11368d75effSDimitry Andric 
11468d75effSDimitry Andric typedef SizeClassAllocator64<AP64> PrimaryAllocator;
1155ffd83dbSDimitry Andric #elif defined(__s390x__)
1165ffd83dbSDimitry Andric static const uptr kMaxAllowedMallocSize = 2UL << 30;  // 2G
1175ffd83dbSDimitry Andric 
1185ffd83dbSDimitry Andric struct AP64 {  // Allocator64 parameters. Deliberately using a short name.
1195ffd83dbSDimitry Andric   static const uptr kSpaceBeg = 0x440000000000;
1205ffd83dbSDimitry Andric   static const uptr kSpaceSize = 0x020000000000;  // 2T.
1215ffd83dbSDimitry Andric   static const uptr kMetadataSize = sizeof(Metadata);
1225ffd83dbSDimitry Andric   typedef DefaultSizeClassMap SizeClassMap;
1235ffd83dbSDimitry Andric   typedef MsanMapUnmapCallback MapUnmapCallback;
1245ffd83dbSDimitry Andric   static const uptr kFlags = 0;
1255ffd83dbSDimitry Andric   using AddressSpaceView = LocalAddressSpaceView;
1265ffd83dbSDimitry Andric };
1275ffd83dbSDimitry Andric 
1285ffd83dbSDimitry Andric typedef SizeClassAllocator64<AP64> PrimaryAllocator;
12968d75effSDimitry Andric #elif defined(__aarch64__)
130bdd1243dSDimitry Andric static const uptr kMaxAllowedMallocSize = 8UL << 30;
13168d75effSDimitry Andric 
132bdd1243dSDimitry Andric struct AP64 {
133bdd1243dSDimitry Andric   static const uptr kSpaceBeg = 0xE00000000000ULL;
134bdd1243dSDimitry Andric   static const uptr kSpaceSize = 0x40000000000;  // 4T.
13568d75effSDimitry Andric   static const uptr kMetadataSize = sizeof(Metadata);
136bdd1243dSDimitry Andric   typedef DefaultSizeClassMap SizeClassMap;
13768d75effSDimitry Andric   typedef MsanMapUnmapCallback MapUnmapCallback;
13868d75effSDimitry Andric   static const uptr kFlags = 0;
139bdd1243dSDimitry Andric   using AddressSpaceView = LocalAddressSpaceView;
14068d75effSDimitry Andric };
141bdd1243dSDimitry Andric typedef SizeClassAllocator64<AP64> PrimaryAllocator;
14268d75effSDimitry Andric #endif
14368d75effSDimitry Andric typedef CombinedAllocator<PrimaryAllocator> Allocator;
14468d75effSDimitry Andric typedef Allocator::AllocatorCache AllocatorCache;
14568d75effSDimitry Andric 
14668d75effSDimitry Andric static Allocator allocator;
14768d75effSDimitry Andric static AllocatorCache fallback_allocator_cache;
14868d75effSDimitry Andric static StaticSpinMutex fallback_mutex;
14968d75effSDimitry Andric 
150480093f4SDimitry Andric static uptr max_malloc_size;
151480093f4SDimitry Andric 
15268d75effSDimitry Andric void MsanAllocatorInit() {
15368d75effSDimitry Andric   SetAllocatorMayReturnNull(common_flags()->allocator_may_return_null);
15468d75effSDimitry Andric   allocator.Init(common_flags()->allocator_release_to_os_interval_ms);
155480093f4SDimitry Andric   if (common_flags()->max_allocation_size_mb)
156480093f4SDimitry Andric     max_malloc_size = Min(common_flags()->max_allocation_size_mb << 20,
157480093f4SDimitry Andric                           kMaxAllowedMallocSize);
158480093f4SDimitry Andric   else
159480093f4SDimitry Andric     max_malloc_size = kMaxAllowedMallocSize;
16068d75effSDimitry Andric }
16168d75effSDimitry Andric 
1625f757f3fSDimitry Andric void LockAllocator() { allocator.ForceLock(); }
1635f757f3fSDimitry Andric 
1645f757f3fSDimitry Andric void UnlockAllocator() { allocator.ForceUnlock(); }
1655f757f3fSDimitry Andric 
16668d75effSDimitry Andric AllocatorCache *GetAllocatorCache(MsanThreadLocalMallocStorage *ms) {
16768d75effSDimitry Andric   CHECK(ms);
16868d75effSDimitry Andric   CHECK_LE(sizeof(AllocatorCache), sizeof(ms->allocator_cache));
16968d75effSDimitry Andric   return reinterpret_cast<AllocatorCache *>(ms->allocator_cache);
17068d75effSDimitry Andric }
17168d75effSDimitry Andric 
17206c3fb27SDimitry Andric void MsanThreadLocalMallocStorage::Init() {
17306c3fb27SDimitry Andric   allocator.InitCache(GetAllocatorCache(this));
17406c3fb27SDimitry Andric }
17506c3fb27SDimitry Andric 
17668d75effSDimitry Andric void MsanThreadLocalMallocStorage::CommitBack() {
17768d75effSDimitry Andric   allocator.SwallowCache(GetAllocatorCache(this));
17806c3fb27SDimitry Andric   allocator.DestroyCache(GetAllocatorCache(this));
17968d75effSDimitry Andric }
18068d75effSDimitry Andric 
181*1db9f3b2SDimitry Andric static void *MsanAllocate(BufferedStackTrace *stack, uptr size, uptr alignment,
18268d75effSDimitry Andric                           bool zeroise) {
183*1db9f3b2SDimitry Andric   if (UNLIKELY(size > max_malloc_size)) {
18468d75effSDimitry Andric     if (AllocatorMayReturnNull()) {
18568d75effSDimitry Andric       Report("WARNING: MemorySanitizer failed to allocate 0x%zx bytes\n", size);
18668d75effSDimitry Andric       return nullptr;
18768d75effSDimitry Andric     }
188*1db9f3b2SDimitry Andric     GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
189480093f4SDimitry Andric     ReportAllocationSizeTooBig(size, max_malloc_size, stack);
19068d75effSDimitry Andric   }
1910eae32dcSDimitry Andric   if (UNLIKELY(IsRssLimitExceeded())) {
1920eae32dcSDimitry Andric     if (AllocatorMayReturnNull())
1930eae32dcSDimitry Andric       return nullptr;
194*1db9f3b2SDimitry Andric     GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
1950eae32dcSDimitry Andric     ReportRssLimitExceeded(stack);
1960eae32dcSDimitry Andric   }
19768d75effSDimitry Andric   MsanThread *t = GetCurrentThread();
19868d75effSDimitry Andric   void *allocated;
19968d75effSDimitry Andric   if (t) {
20068d75effSDimitry Andric     AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
20168d75effSDimitry Andric     allocated = allocator.Allocate(cache, size, alignment);
20268d75effSDimitry Andric   } else {
20368d75effSDimitry Andric     SpinMutexLock l(&fallback_mutex);
20468d75effSDimitry Andric     AllocatorCache *cache = &fallback_allocator_cache;
20568d75effSDimitry Andric     allocated = allocator.Allocate(cache, size, alignment);
20668d75effSDimitry Andric   }
20768d75effSDimitry Andric   if (UNLIKELY(!allocated)) {
20868d75effSDimitry Andric     SetAllocatorOutOfMemory();
20968d75effSDimitry Andric     if (AllocatorMayReturnNull())
21068d75effSDimitry Andric       return nullptr;
211*1db9f3b2SDimitry Andric     GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
21268d75effSDimitry Andric     ReportOutOfMemory(size, stack);
21368d75effSDimitry Andric   }
21468d75effSDimitry Andric   Metadata *meta =
21568d75effSDimitry Andric       reinterpret_cast<Metadata *>(allocator.GetMetaData(allocated));
21668d75effSDimitry Andric   meta->requested_size = size;
21768d75effSDimitry Andric   if (zeroise) {
21806c3fb27SDimitry Andric     if (allocator.FromPrimary(allocated))
21968d75effSDimitry Andric       __msan_clear_and_unpoison(allocated, size);
22006c3fb27SDimitry Andric     else
22106c3fb27SDimitry Andric       __msan_unpoison(allocated, size);  // Mem is already zeroed.
22268d75effSDimitry Andric   } else if (flags()->poison_in_malloc) {
22368d75effSDimitry Andric     __msan_poison(allocated, size);
22468d75effSDimitry Andric     if (__msan_get_track_origins()) {
22568d75effSDimitry Andric       stack->tag = StackTrace::TAG_ALLOC;
22668d75effSDimitry Andric       Origin o = Origin::CreateHeapOrigin(stack);
22768d75effSDimitry Andric       __msan_set_origin(allocated, size, o.raw_id());
22868d75effSDimitry Andric     }
22968d75effSDimitry Andric   }
23081ad6265SDimitry Andric   UnpoisonParam(2);
23181ad6265SDimitry Andric   RunMallocHooks(allocated, size);
23268d75effSDimitry Andric   return allocated;
23368d75effSDimitry Andric }
23468d75effSDimitry Andric 
235*1db9f3b2SDimitry Andric void MsanDeallocate(BufferedStackTrace *stack, void *p) {
23668d75effSDimitry Andric   CHECK(p);
23781ad6265SDimitry Andric   UnpoisonParam(1);
23881ad6265SDimitry Andric   RunFreeHooks(p);
23981ad6265SDimitry Andric 
24068d75effSDimitry Andric   Metadata *meta = reinterpret_cast<Metadata *>(allocator.GetMetaData(p));
24168d75effSDimitry Andric   uptr size = meta->requested_size;
24268d75effSDimitry Andric   meta->requested_size = 0;
24368d75effSDimitry Andric   // This memory will not be reused by anyone else, so we are free to keep it
24406c3fb27SDimitry Andric   // poisoned. The secondary allocator will unmap and unpoison by
24506c3fb27SDimitry Andric   // MsanMapUnmapCallback, no need to poison it here.
24606c3fb27SDimitry Andric   if (flags()->poison_in_free && allocator.FromPrimary(p)) {
24768d75effSDimitry Andric     __msan_poison(p, size);
24868d75effSDimitry Andric     if (__msan_get_track_origins()) {
24968d75effSDimitry Andric       stack->tag = StackTrace::TAG_DEALLOC;
25068d75effSDimitry Andric       Origin o = Origin::CreateHeapOrigin(stack);
25168d75effSDimitry Andric       __msan_set_origin(p, size, o.raw_id());
25268d75effSDimitry Andric     }
25368d75effSDimitry Andric   }
25468d75effSDimitry Andric   MsanThread *t = GetCurrentThread();
25568d75effSDimitry Andric   if (t) {
25668d75effSDimitry Andric     AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
25768d75effSDimitry Andric     allocator.Deallocate(cache, p);
25868d75effSDimitry Andric   } else {
25968d75effSDimitry Andric     SpinMutexLock l(&fallback_mutex);
26068d75effSDimitry Andric     AllocatorCache *cache = &fallback_allocator_cache;
26168d75effSDimitry Andric     allocator.Deallocate(cache, p);
26268d75effSDimitry Andric   }
26368d75effSDimitry Andric }
26468d75effSDimitry Andric 
265*1db9f3b2SDimitry Andric static void *MsanReallocate(BufferedStackTrace *stack, void *old_p,
266*1db9f3b2SDimitry Andric                             uptr new_size, uptr alignment) {
26768d75effSDimitry Andric   Metadata *meta = reinterpret_cast<Metadata*>(allocator.GetMetaData(old_p));
26868d75effSDimitry Andric   uptr old_size = meta->requested_size;
26968d75effSDimitry Andric   uptr actually_allocated_size = allocator.GetActuallyAllocatedSize(old_p);
27068d75effSDimitry Andric   if (new_size <= actually_allocated_size) {
27168d75effSDimitry Andric     // We are not reallocating here.
27268d75effSDimitry Andric     meta->requested_size = new_size;
27368d75effSDimitry Andric     if (new_size > old_size) {
27468d75effSDimitry Andric       if (flags()->poison_in_malloc) {
27568d75effSDimitry Andric         stack->tag = StackTrace::TAG_ALLOC;
27668d75effSDimitry Andric         PoisonMemory((char *)old_p + old_size, new_size - old_size, stack);
27768d75effSDimitry Andric       }
27868d75effSDimitry Andric     }
27968d75effSDimitry Andric     return old_p;
28068d75effSDimitry Andric   }
28168d75effSDimitry Andric   uptr memcpy_size = Min(new_size, old_size);
28268d75effSDimitry Andric   void *new_p = MsanAllocate(stack, new_size, alignment, false /*zeroise*/);
28368d75effSDimitry Andric   if (new_p) {
28468d75effSDimitry Andric     CopyMemory(new_p, old_p, memcpy_size, stack);
28568d75effSDimitry Andric     MsanDeallocate(stack, old_p);
28668d75effSDimitry Andric   }
28768d75effSDimitry Andric   return new_p;
28868d75effSDimitry Andric }
28968d75effSDimitry Andric 
290*1db9f3b2SDimitry Andric static void *MsanCalloc(BufferedStackTrace *stack, uptr nmemb, uptr size) {
29168d75effSDimitry Andric   if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
29268d75effSDimitry Andric     if (AllocatorMayReturnNull())
29368d75effSDimitry Andric       return nullptr;
294*1db9f3b2SDimitry Andric     GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
29568d75effSDimitry Andric     ReportCallocOverflow(nmemb, size, stack);
29668d75effSDimitry Andric   }
29768d75effSDimitry Andric   return MsanAllocate(stack, nmemb * size, sizeof(u64), true);
29868d75effSDimitry Andric }
29968d75effSDimitry Andric 
30006c3fb27SDimitry Andric static const void *AllocationBegin(const void *p) {
30106c3fb27SDimitry Andric   if (!p)
30206c3fb27SDimitry Andric     return nullptr;
30306c3fb27SDimitry Andric   void *beg = allocator.GetBlockBegin(p);
30406c3fb27SDimitry Andric   if (!beg)
30506c3fb27SDimitry Andric     return nullptr;
30606c3fb27SDimitry Andric   Metadata *b = (Metadata *)allocator.GetMetaData(beg);
30706c3fb27SDimitry Andric   if (!b)
30806c3fb27SDimitry Andric     return nullptr;
30906c3fb27SDimitry Andric   if (b->requested_size == 0)
31006c3fb27SDimitry Andric     return nullptr;
31106c3fb27SDimitry Andric 
31206c3fb27SDimitry Andric   return (const void *)beg;
31306c3fb27SDimitry Andric }
31406c3fb27SDimitry Andric 
31568d75effSDimitry Andric static uptr AllocationSize(const void *p) {
31668d75effSDimitry Andric   if (!p) return 0;
31768d75effSDimitry Andric   const void *beg = allocator.GetBlockBegin(p);
31868d75effSDimitry Andric   if (beg != p) return 0;
31968d75effSDimitry Andric   Metadata *b = (Metadata *)allocator.GetMetaData(p);
32068d75effSDimitry Andric   return b->requested_size;
32168d75effSDimitry Andric }
32268d75effSDimitry Andric 
32306c3fb27SDimitry Andric static uptr AllocationSizeFast(const void *p) {
32406c3fb27SDimitry Andric   return reinterpret_cast<Metadata *>(allocator.GetMetaData(p))->requested_size;
32506c3fb27SDimitry Andric }
32606c3fb27SDimitry Andric 
327*1db9f3b2SDimitry Andric void *msan_malloc(uptr size, BufferedStackTrace *stack) {
32868d75effSDimitry Andric   return SetErrnoOnNull(MsanAllocate(stack, size, sizeof(u64), false));
32968d75effSDimitry Andric }
33068d75effSDimitry Andric 
331*1db9f3b2SDimitry Andric void *msan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack) {
33268d75effSDimitry Andric   return SetErrnoOnNull(MsanCalloc(stack, nmemb, size));
33368d75effSDimitry Andric }
33468d75effSDimitry Andric 
335*1db9f3b2SDimitry Andric void *msan_realloc(void *ptr, uptr size, BufferedStackTrace *stack) {
33668d75effSDimitry Andric   if (!ptr)
33768d75effSDimitry Andric     return SetErrnoOnNull(MsanAllocate(stack, size, sizeof(u64), false));
33868d75effSDimitry Andric   if (size == 0) {
33968d75effSDimitry Andric     MsanDeallocate(stack, ptr);
34068d75effSDimitry Andric     return nullptr;
34168d75effSDimitry Andric   }
34268d75effSDimitry Andric   return SetErrnoOnNull(MsanReallocate(stack, ptr, size, sizeof(u64)));
34368d75effSDimitry Andric }
34468d75effSDimitry Andric 
345*1db9f3b2SDimitry Andric void *msan_reallocarray(void *ptr, uptr nmemb, uptr size,
346*1db9f3b2SDimitry Andric                         BufferedStackTrace *stack) {
34768d75effSDimitry Andric   if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) {
34868d75effSDimitry Andric     errno = errno_ENOMEM;
34968d75effSDimitry Andric     if (AllocatorMayReturnNull())
35068d75effSDimitry Andric       return nullptr;
351*1db9f3b2SDimitry Andric     GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
35268d75effSDimitry Andric     ReportReallocArrayOverflow(nmemb, size, stack);
35368d75effSDimitry Andric   }
35468d75effSDimitry Andric   return msan_realloc(ptr, nmemb * size, stack);
35568d75effSDimitry Andric }
35668d75effSDimitry Andric 
357*1db9f3b2SDimitry Andric void *msan_valloc(uptr size, BufferedStackTrace *stack) {
35868d75effSDimitry Andric   return SetErrnoOnNull(MsanAllocate(stack, size, GetPageSizeCached(), false));
35968d75effSDimitry Andric }
36068d75effSDimitry Andric 
361*1db9f3b2SDimitry Andric void *msan_pvalloc(uptr size, BufferedStackTrace *stack) {
36268d75effSDimitry Andric   uptr PageSize = GetPageSizeCached();
36368d75effSDimitry Andric   if (UNLIKELY(CheckForPvallocOverflow(size, PageSize))) {
36468d75effSDimitry Andric     errno = errno_ENOMEM;
36568d75effSDimitry Andric     if (AllocatorMayReturnNull())
36668d75effSDimitry Andric       return nullptr;
367*1db9f3b2SDimitry Andric     GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
36868d75effSDimitry Andric     ReportPvallocOverflow(size, stack);
36968d75effSDimitry Andric   }
37068d75effSDimitry Andric   // pvalloc(0) should allocate one page.
37168d75effSDimitry Andric   size = size ? RoundUpTo(size, PageSize) : PageSize;
37268d75effSDimitry Andric   return SetErrnoOnNull(MsanAllocate(stack, size, PageSize, false));
37368d75effSDimitry Andric }
37468d75effSDimitry Andric 
375*1db9f3b2SDimitry Andric void *msan_aligned_alloc(uptr alignment, uptr size, BufferedStackTrace *stack) {
37668d75effSDimitry Andric   if (UNLIKELY(!CheckAlignedAllocAlignmentAndSize(alignment, size))) {
37768d75effSDimitry Andric     errno = errno_EINVAL;
37868d75effSDimitry Andric     if (AllocatorMayReturnNull())
37968d75effSDimitry Andric       return nullptr;
380*1db9f3b2SDimitry Andric     GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
38168d75effSDimitry Andric     ReportInvalidAlignedAllocAlignment(size, alignment, stack);
38268d75effSDimitry Andric   }
38368d75effSDimitry Andric   return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false));
38468d75effSDimitry Andric }
38568d75effSDimitry Andric 
386*1db9f3b2SDimitry Andric void *msan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack) {
38768d75effSDimitry Andric   if (UNLIKELY(!IsPowerOfTwo(alignment))) {
38868d75effSDimitry Andric     errno = errno_EINVAL;
38968d75effSDimitry Andric     if (AllocatorMayReturnNull())
39068d75effSDimitry Andric       return nullptr;
391*1db9f3b2SDimitry Andric     GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
39268d75effSDimitry Andric     ReportInvalidAllocationAlignment(alignment, stack);
39368d75effSDimitry Andric   }
39468d75effSDimitry Andric   return SetErrnoOnNull(MsanAllocate(stack, size, alignment, false));
39568d75effSDimitry Andric }
39668d75effSDimitry Andric 
39768d75effSDimitry Andric int msan_posix_memalign(void **memptr, uptr alignment, uptr size,
398*1db9f3b2SDimitry Andric                         BufferedStackTrace *stack) {
39968d75effSDimitry Andric   if (UNLIKELY(!CheckPosixMemalignAlignment(alignment))) {
40068d75effSDimitry Andric     if (AllocatorMayReturnNull())
40168d75effSDimitry Andric       return errno_EINVAL;
402*1db9f3b2SDimitry Andric     GET_FATAL_STACK_TRACE_IF_EMPTY(stack);
40368d75effSDimitry Andric     ReportInvalidPosixMemalignAlignment(alignment, stack);
40468d75effSDimitry Andric   }
40568d75effSDimitry Andric   void *ptr = MsanAllocate(stack, size, alignment, false);
40668d75effSDimitry Andric   if (UNLIKELY(!ptr))
40768d75effSDimitry Andric     // OOM error is already taken care of by MsanAllocate.
40868d75effSDimitry Andric     return errno_ENOMEM;
40968d75effSDimitry Andric   CHECK(IsAligned((uptr)ptr, alignment));
41068d75effSDimitry Andric   *memptr = ptr;
41168d75effSDimitry Andric   return 0;
41268d75effSDimitry Andric }
41368d75effSDimitry Andric 
41468d75effSDimitry Andric } // namespace __msan
41568d75effSDimitry Andric 
41668d75effSDimitry Andric using namespace __msan;
41768d75effSDimitry Andric 
41868d75effSDimitry Andric uptr __sanitizer_get_current_allocated_bytes() {
41968d75effSDimitry Andric   uptr stats[AllocatorStatCount];
42068d75effSDimitry Andric   allocator.GetStats(stats);
42168d75effSDimitry Andric   return stats[AllocatorStatAllocated];
42268d75effSDimitry Andric }
42368d75effSDimitry Andric 
42468d75effSDimitry Andric uptr __sanitizer_get_heap_size() {
42568d75effSDimitry Andric   uptr stats[AllocatorStatCount];
42668d75effSDimitry Andric   allocator.GetStats(stats);
42768d75effSDimitry Andric   return stats[AllocatorStatMapped];
42868d75effSDimitry Andric }
42968d75effSDimitry Andric 
43068d75effSDimitry Andric uptr __sanitizer_get_free_bytes() { return 1; }
43168d75effSDimitry Andric 
43268d75effSDimitry Andric uptr __sanitizer_get_unmapped_bytes() { return 1; }
43368d75effSDimitry Andric 
43468d75effSDimitry Andric uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; }
43568d75effSDimitry Andric 
43668d75effSDimitry Andric int __sanitizer_get_ownership(const void *p) { return AllocationSize(p) != 0; }
43768d75effSDimitry Andric 
43806c3fb27SDimitry Andric const void *__sanitizer_get_allocated_begin(const void *p) {
43906c3fb27SDimitry Andric   return AllocationBegin(p);
44006c3fb27SDimitry Andric }
44106c3fb27SDimitry Andric 
44268d75effSDimitry Andric uptr __sanitizer_get_allocated_size(const void *p) { return AllocationSize(p); }
44306c3fb27SDimitry Andric 
44406c3fb27SDimitry Andric uptr __sanitizer_get_allocated_size_fast(const void *p) {
44506c3fb27SDimitry Andric   DCHECK_EQ(p, __sanitizer_get_allocated_begin(p));
44606c3fb27SDimitry Andric   uptr ret = AllocationSizeFast(p);
44706c3fb27SDimitry Andric   DCHECK_EQ(ret, __sanitizer_get_allocated_size(p));
44806c3fb27SDimitry Andric   return ret;
44906c3fb27SDimitry Andric }
45006c3fb27SDimitry Andric 
45106c3fb27SDimitry Andric void __sanitizer_purge_allocator() { allocator.ForceReleaseToOS(); }
452