168d75effSDimitry Andric //=-- lsan_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 LeakSanitizer. 1068d75effSDimitry Andric // See lsan_allocator.h for details. 1168d75effSDimitry Andric // 1268d75effSDimitry Andric //===----------------------------------------------------------------------===// 1368d75effSDimitry Andric 1468d75effSDimitry Andric #include "lsan_allocator.h" 1568d75effSDimitry Andric 1668d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator.h" 1768d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator_checks.h" 1868d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator_interface.h" 1968d75effSDimitry Andric #include "sanitizer_common/sanitizer_allocator_report.h" 2068d75effSDimitry Andric #include "sanitizer_common/sanitizer_errno.h" 2168d75effSDimitry Andric #include "sanitizer_common/sanitizer_internal_defs.h" 2268d75effSDimitry Andric #include "sanitizer_common/sanitizer_stackdepot.h" 2368d75effSDimitry Andric #include "sanitizer_common/sanitizer_stacktrace.h" 2468d75effSDimitry Andric #include "lsan_common.h" 2568d75effSDimitry Andric 2668d75effSDimitry Andric extern "C" void *memset(void *ptr, int value, uptr num); 2768d75effSDimitry Andric 2868d75effSDimitry Andric namespace __lsan { 2968d75effSDimitry Andric #if defined(__i386__) || defined(__arm__) 300eae32dcSDimitry Andric static const uptr kMaxAllowedMallocSize = 1ULL << 30; 3168d75effSDimitry Andric #elif defined(__mips64) || defined(__aarch64__) 320eae32dcSDimitry Andric static const uptr kMaxAllowedMallocSize = 4ULL << 30; 3368d75effSDimitry Andric #else 34*0fca6ea1SDimitry Andric static const uptr kMaxAllowedMallocSize = 1ULL << 40; 3568d75effSDimitry Andric #endif 3668d75effSDimitry Andric 3768d75effSDimitry Andric static Allocator allocator; 3868d75effSDimitry Andric 39480093f4SDimitry Andric static uptr max_malloc_size; 40480093f4SDimitry Andric 4168d75effSDimitry Andric void InitializeAllocator() { 4268d75effSDimitry Andric SetAllocatorMayReturnNull(common_flags()->allocator_may_return_null); 4368d75effSDimitry Andric allocator.InitLinkerInitialized( 4468d75effSDimitry Andric common_flags()->allocator_release_to_os_interval_ms); 45480093f4SDimitry Andric if (common_flags()->max_allocation_size_mb) 46480093f4SDimitry Andric max_malloc_size = Min(common_flags()->max_allocation_size_mb << 20, 47480093f4SDimitry Andric kMaxAllowedMallocSize); 48480093f4SDimitry Andric else 49480093f4SDimitry Andric max_malloc_size = kMaxAllowedMallocSize; 5068d75effSDimitry Andric } 5168d75effSDimitry Andric 5206c3fb27SDimitry Andric void AllocatorThreadStart() { allocator.InitCache(GetAllocatorCache()); } 5306c3fb27SDimitry Andric 5468d75effSDimitry Andric void AllocatorThreadFinish() { 5568d75effSDimitry Andric allocator.SwallowCache(GetAllocatorCache()); 5606c3fb27SDimitry Andric allocator.DestroyCache(GetAllocatorCache()); 5768d75effSDimitry Andric } 5868d75effSDimitry Andric 5968d75effSDimitry Andric static ChunkMetadata *Metadata(const void *p) { 6068d75effSDimitry Andric return reinterpret_cast<ChunkMetadata *>(allocator.GetMetaData(p)); 6168d75effSDimitry Andric } 6268d75effSDimitry Andric 6368d75effSDimitry Andric static void RegisterAllocation(const StackTrace &stack, void *p, uptr size) { 6468d75effSDimitry Andric if (!p) return; 6568d75effSDimitry Andric ChunkMetadata *m = Metadata(p); 6668d75effSDimitry Andric CHECK(m); 6768d75effSDimitry Andric m->tag = DisabledInThisThread() ? kIgnored : kDirectlyLeaked; 6868d75effSDimitry Andric m->stack_trace_id = StackDepotPut(stack); 6968d75effSDimitry Andric m->requested_size = size; 7068d75effSDimitry Andric atomic_store(reinterpret_cast<atomic_uint8_t *>(m), 1, memory_order_relaxed); 7106c3fb27SDimitry Andric RunMallocHooks(p, size); 7268d75effSDimitry Andric } 7368d75effSDimitry Andric 7468d75effSDimitry Andric static void RegisterDeallocation(void *p) { 7568d75effSDimitry Andric if (!p) return; 7668d75effSDimitry Andric ChunkMetadata *m = Metadata(p); 7768d75effSDimitry Andric CHECK(m); 7806c3fb27SDimitry Andric RunFreeHooks(p); 7968d75effSDimitry Andric atomic_store(reinterpret_cast<atomic_uint8_t *>(m), 0, memory_order_relaxed); 8068d75effSDimitry Andric } 8168d75effSDimitry Andric 8268d75effSDimitry Andric static void *ReportAllocationSizeTooBig(uptr size, const StackTrace &stack) { 8368d75effSDimitry Andric if (AllocatorMayReturnNull()) { 8468d75effSDimitry Andric Report("WARNING: LeakSanitizer failed to allocate 0x%zx bytes\n", size); 8568d75effSDimitry Andric return nullptr; 8668d75effSDimitry Andric } 87480093f4SDimitry Andric ReportAllocationSizeTooBig(size, max_malloc_size, &stack); 8868d75effSDimitry Andric } 8968d75effSDimitry Andric 9068d75effSDimitry Andric void *Allocate(const StackTrace &stack, uptr size, uptr alignment, 9168d75effSDimitry Andric bool cleared) { 9268d75effSDimitry Andric if (size == 0) 9368d75effSDimitry Andric size = 1; 94480093f4SDimitry Andric if (size > max_malloc_size) 9568d75effSDimitry Andric return ReportAllocationSizeTooBig(size, stack); 960eae32dcSDimitry Andric if (UNLIKELY(IsRssLimitExceeded())) { 970eae32dcSDimitry Andric if (AllocatorMayReturnNull()) 980eae32dcSDimitry Andric return nullptr; 990eae32dcSDimitry Andric ReportRssLimitExceeded(&stack); 1000eae32dcSDimitry Andric } 10168d75effSDimitry Andric void *p = allocator.Allocate(GetAllocatorCache(), size, alignment); 10268d75effSDimitry Andric if (UNLIKELY(!p)) { 10368d75effSDimitry Andric SetAllocatorOutOfMemory(); 10468d75effSDimitry Andric if (AllocatorMayReturnNull()) 10568d75effSDimitry Andric return nullptr; 10668d75effSDimitry Andric ReportOutOfMemory(size, &stack); 10768d75effSDimitry Andric } 10868d75effSDimitry Andric // Do not rely on the allocator to clear the memory (it's slow). 10968d75effSDimitry Andric if (cleared && allocator.FromPrimary(p)) 11068d75effSDimitry Andric memset(p, 0, size); 11168d75effSDimitry Andric RegisterAllocation(stack, p, size); 11268d75effSDimitry Andric return p; 11368d75effSDimitry Andric } 11468d75effSDimitry Andric 11568d75effSDimitry Andric static void *Calloc(uptr nmemb, uptr size, const StackTrace &stack) { 11668d75effSDimitry Andric if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) { 11768d75effSDimitry Andric if (AllocatorMayReturnNull()) 11868d75effSDimitry Andric return nullptr; 11968d75effSDimitry Andric ReportCallocOverflow(nmemb, size, &stack); 12068d75effSDimitry Andric } 12168d75effSDimitry Andric size *= nmemb; 12268d75effSDimitry Andric return Allocate(stack, size, 1, true); 12368d75effSDimitry Andric } 12468d75effSDimitry Andric 12568d75effSDimitry Andric void Deallocate(void *p) { 12668d75effSDimitry Andric RegisterDeallocation(p); 12768d75effSDimitry Andric allocator.Deallocate(GetAllocatorCache(), p); 12868d75effSDimitry Andric } 12968d75effSDimitry Andric 13068d75effSDimitry Andric void *Reallocate(const StackTrace &stack, void *p, uptr new_size, 13168d75effSDimitry Andric uptr alignment) { 132480093f4SDimitry Andric if (new_size > max_malloc_size) { 133fe6060f1SDimitry Andric ReportAllocationSizeTooBig(new_size, stack); 134fe6060f1SDimitry Andric return nullptr; 13568d75effSDimitry Andric } 136fe6060f1SDimitry Andric RegisterDeallocation(p); 137fe6060f1SDimitry Andric void *new_p = 138fe6060f1SDimitry Andric allocator.Reallocate(GetAllocatorCache(), p, new_size, alignment); 139fe6060f1SDimitry Andric if (new_p) 140fe6060f1SDimitry Andric RegisterAllocation(stack, new_p, new_size); 141fe6060f1SDimitry Andric else if (new_size != 0) 14268d75effSDimitry Andric RegisterAllocation(stack, p, new_size); 143fe6060f1SDimitry Andric return new_p; 14468d75effSDimitry Andric } 14568d75effSDimitry Andric 14668d75effSDimitry Andric void GetAllocatorCacheRange(uptr *begin, uptr *end) { 14768d75effSDimitry Andric *begin = (uptr)GetAllocatorCache(); 14868d75effSDimitry Andric *end = *begin + sizeof(AllocatorCache); 14968d75effSDimitry Andric } 15068d75effSDimitry Andric 15106c3fb27SDimitry Andric static const void *GetMallocBegin(const void *p) { 15206c3fb27SDimitry Andric if (!p) 15306c3fb27SDimitry Andric return nullptr; 15406c3fb27SDimitry Andric void *beg = allocator.GetBlockBegin(p); 15506c3fb27SDimitry Andric if (!beg) 15606c3fb27SDimitry Andric return nullptr; 15706c3fb27SDimitry Andric ChunkMetadata *m = Metadata(beg); 15806c3fb27SDimitry Andric if (!m) 15906c3fb27SDimitry Andric return nullptr; 16006c3fb27SDimitry Andric if (!m->allocated) 16106c3fb27SDimitry Andric return nullptr; 16206c3fb27SDimitry Andric if (m->requested_size == 0) 16306c3fb27SDimitry Andric return nullptr; 16406c3fb27SDimitry Andric return (const void *)beg; 16506c3fb27SDimitry Andric } 16606c3fb27SDimitry Andric 16768d75effSDimitry Andric uptr GetMallocUsableSize(const void *p) { 16881ad6265SDimitry Andric if (!p) 16981ad6265SDimitry Andric return 0; 17068d75effSDimitry Andric ChunkMetadata *m = Metadata(p); 17168d75effSDimitry Andric if (!m) return 0; 17268d75effSDimitry Andric return m->requested_size; 17368d75effSDimitry Andric } 17468d75effSDimitry Andric 17506c3fb27SDimitry Andric uptr GetMallocUsableSizeFast(const void *p) { 17606c3fb27SDimitry Andric return Metadata(p)->requested_size; 17706c3fb27SDimitry Andric } 17806c3fb27SDimitry Andric 17968d75effSDimitry Andric int lsan_posix_memalign(void **memptr, uptr alignment, uptr size, 18068d75effSDimitry Andric const StackTrace &stack) { 18168d75effSDimitry Andric if (UNLIKELY(!CheckPosixMemalignAlignment(alignment))) { 18268d75effSDimitry Andric if (AllocatorMayReturnNull()) 18368d75effSDimitry Andric return errno_EINVAL; 18468d75effSDimitry Andric ReportInvalidPosixMemalignAlignment(alignment, &stack); 18568d75effSDimitry Andric } 18668d75effSDimitry Andric void *ptr = Allocate(stack, size, alignment, kAlwaysClearMemory); 18768d75effSDimitry Andric if (UNLIKELY(!ptr)) 18868d75effSDimitry Andric // OOM error is already taken care of by Allocate. 18968d75effSDimitry Andric return errno_ENOMEM; 19068d75effSDimitry Andric CHECK(IsAligned((uptr)ptr, alignment)); 19168d75effSDimitry Andric *memptr = ptr; 19268d75effSDimitry Andric return 0; 19368d75effSDimitry Andric } 19468d75effSDimitry Andric 19568d75effSDimitry Andric void *lsan_aligned_alloc(uptr alignment, uptr size, const StackTrace &stack) { 19668d75effSDimitry Andric if (UNLIKELY(!CheckAlignedAllocAlignmentAndSize(alignment, size))) { 19768d75effSDimitry Andric errno = errno_EINVAL; 19868d75effSDimitry Andric if (AllocatorMayReturnNull()) 19968d75effSDimitry Andric return nullptr; 20068d75effSDimitry Andric ReportInvalidAlignedAllocAlignment(size, alignment, &stack); 20168d75effSDimitry Andric } 20268d75effSDimitry Andric return SetErrnoOnNull(Allocate(stack, size, alignment, kAlwaysClearMemory)); 20368d75effSDimitry Andric } 20468d75effSDimitry Andric 20568d75effSDimitry Andric void *lsan_memalign(uptr alignment, uptr size, const StackTrace &stack) { 20668d75effSDimitry Andric if (UNLIKELY(!IsPowerOfTwo(alignment))) { 20768d75effSDimitry Andric errno = errno_EINVAL; 20868d75effSDimitry Andric if (AllocatorMayReturnNull()) 20968d75effSDimitry Andric return nullptr; 21068d75effSDimitry Andric ReportInvalidAllocationAlignment(alignment, &stack); 21168d75effSDimitry Andric } 21268d75effSDimitry Andric return SetErrnoOnNull(Allocate(stack, size, alignment, kAlwaysClearMemory)); 21368d75effSDimitry Andric } 21468d75effSDimitry Andric 21568d75effSDimitry Andric void *lsan_malloc(uptr size, const StackTrace &stack) { 21668d75effSDimitry Andric return SetErrnoOnNull(Allocate(stack, size, 1, kAlwaysClearMemory)); 21768d75effSDimitry Andric } 21868d75effSDimitry Andric 21968d75effSDimitry Andric void lsan_free(void *p) { 22068d75effSDimitry Andric Deallocate(p); 22168d75effSDimitry Andric } 22268d75effSDimitry Andric 22368d75effSDimitry Andric void *lsan_realloc(void *p, uptr size, const StackTrace &stack) { 22468d75effSDimitry Andric return SetErrnoOnNull(Reallocate(stack, p, size, 1)); 22568d75effSDimitry Andric } 22668d75effSDimitry Andric 22768d75effSDimitry Andric void *lsan_reallocarray(void *ptr, uptr nmemb, uptr size, 22868d75effSDimitry Andric const StackTrace &stack) { 22968d75effSDimitry Andric if (UNLIKELY(CheckForCallocOverflow(size, nmemb))) { 23068d75effSDimitry Andric errno = errno_ENOMEM; 23168d75effSDimitry Andric if (AllocatorMayReturnNull()) 23268d75effSDimitry Andric return nullptr; 23368d75effSDimitry Andric ReportReallocArrayOverflow(nmemb, size, &stack); 23468d75effSDimitry Andric } 23568d75effSDimitry Andric return lsan_realloc(ptr, nmemb * size, stack); 23668d75effSDimitry Andric } 23768d75effSDimitry Andric 23868d75effSDimitry Andric void *lsan_calloc(uptr nmemb, uptr size, const StackTrace &stack) { 23968d75effSDimitry Andric return SetErrnoOnNull(Calloc(nmemb, size, stack)); 24068d75effSDimitry Andric } 24168d75effSDimitry Andric 24268d75effSDimitry Andric void *lsan_valloc(uptr size, const StackTrace &stack) { 24368d75effSDimitry Andric return SetErrnoOnNull( 24468d75effSDimitry Andric Allocate(stack, size, GetPageSizeCached(), kAlwaysClearMemory)); 24568d75effSDimitry Andric } 24668d75effSDimitry Andric 24768d75effSDimitry Andric void *lsan_pvalloc(uptr size, const StackTrace &stack) { 24868d75effSDimitry Andric uptr PageSize = GetPageSizeCached(); 24968d75effSDimitry Andric if (UNLIKELY(CheckForPvallocOverflow(size, PageSize))) { 25068d75effSDimitry Andric errno = errno_ENOMEM; 25168d75effSDimitry Andric if (AllocatorMayReturnNull()) 25268d75effSDimitry Andric return nullptr; 25368d75effSDimitry Andric ReportPvallocOverflow(size, &stack); 25468d75effSDimitry Andric } 25568d75effSDimitry Andric // pvalloc(0) should allocate one page. 25668d75effSDimitry Andric size = size ? RoundUpTo(size, PageSize) : PageSize; 25768d75effSDimitry Andric return SetErrnoOnNull(Allocate(stack, size, PageSize, kAlwaysClearMemory)); 25868d75effSDimitry Andric } 25968d75effSDimitry Andric 26068d75effSDimitry Andric uptr lsan_mz_size(const void *p) { 26168d75effSDimitry Andric return GetMallocUsableSize(p); 26268d75effSDimitry Andric } 26368d75effSDimitry Andric 26468d75effSDimitry Andric ///// Interface to the common LSan module. ///// 26568d75effSDimitry Andric 26668d75effSDimitry Andric void LockAllocator() { 26768d75effSDimitry Andric allocator.ForceLock(); 26868d75effSDimitry Andric } 26968d75effSDimitry Andric 27068d75effSDimitry Andric void UnlockAllocator() { 27168d75effSDimitry Andric allocator.ForceUnlock(); 27268d75effSDimitry Andric } 27368d75effSDimitry Andric 27468d75effSDimitry Andric void GetAllocatorGlobalRange(uptr *begin, uptr *end) { 27568d75effSDimitry Andric *begin = (uptr)&allocator; 27668d75effSDimitry Andric *end = *begin + sizeof(allocator); 27768d75effSDimitry Andric } 27868d75effSDimitry Andric 27968d75effSDimitry Andric uptr PointsIntoChunk(void* p) { 28068d75effSDimitry Andric uptr addr = reinterpret_cast<uptr>(p); 28168d75effSDimitry Andric uptr chunk = reinterpret_cast<uptr>(allocator.GetBlockBeginFastLocked(p)); 28268d75effSDimitry Andric if (!chunk) return 0; 28368d75effSDimitry Andric // LargeMmapAllocator considers pointers to the meta-region of a chunk to be 28468d75effSDimitry Andric // valid, but we don't want that. 28568d75effSDimitry Andric if (addr < chunk) return 0; 28668d75effSDimitry Andric ChunkMetadata *m = Metadata(reinterpret_cast<void *>(chunk)); 28768d75effSDimitry Andric CHECK(m); 28868d75effSDimitry Andric if (!m->allocated) 28968d75effSDimitry Andric return 0; 29068d75effSDimitry Andric if (addr < chunk + m->requested_size) 29168d75effSDimitry Andric return chunk; 29268d75effSDimitry Andric if (IsSpecialCaseOfOperatorNew0(chunk, m->requested_size, addr)) 29368d75effSDimitry Andric return chunk; 29468d75effSDimitry Andric return 0; 29568d75effSDimitry Andric } 29668d75effSDimitry Andric 29768d75effSDimitry Andric uptr GetUserBegin(uptr chunk) { 29868d75effSDimitry Andric return chunk; 29968d75effSDimitry Andric } 30068d75effSDimitry Andric 30106c3fb27SDimitry Andric uptr GetUserAddr(uptr chunk) { 30206c3fb27SDimitry Andric return chunk; 30306c3fb27SDimitry Andric } 30406c3fb27SDimitry Andric 30568d75effSDimitry Andric LsanMetadata::LsanMetadata(uptr chunk) { 30668d75effSDimitry Andric metadata_ = Metadata(reinterpret_cast<void *>(chunk)); 30768d75effSDimitry Andric CHECK(metadata_); 30868d75effSDimitry Andric } 30968d75effSDimitry Andric 31068d75effSDimitry Andric bool LsanMetadata::allocated() const { 31168d75effSDimitry Andric return reinterpret_cast<ChunkMetadata *>(metadata_)->allocated; 31268d75effSDimitry Andric } 31368d75effSDimitry Andric 31468d75effSDimitry Andric ChunkTag LsanMetadata::tag() const { 31568d75effSDimitry Andric return reinterpret_cast<ChunkMetadata *>(metadata_)->tag; 31668d75effSDimitry Andric } 31768d75effSDimitry Andric 31868d75effSDimitry Andric void LsanMetadata::set_tag(ChunkTag value) { 31968d75effSDimitry Andric reinterpret_cast<ChunkMetadata *>(metadata_)->tag = value; 32068d75effSDimitry Andric } 32168d75effSDimitry Andric 32268d75effSDimitry Andric uptr LsanMetadata::requested_size() const { 32368d75effSDimitry Andric return reinterpret_cast<ChunkMetadata *>(metadata_)->requested_size; 32468d75effSDimitry Andric } 32568d75effSDimitry Andric 32668d75effSDimitry Andric u32 LsanMetadata::stack_trace_id() const { 32768d75effSDimitry Andric return reinterpret_cast<ChunkMetadata *>(metadata_)->stack_trace_id; 32868d75effSDimitry Andric } 32968d75effSDimitry Andric 33068d75effSDimitry Andric void ForEachChunk(ForEachChunkCallback callback, void *arg) { 33168d75effSDimitry Andric allocator.ForEachChunk(callback, arg); 33268d75effSDimitry Andric } 33368d75effSDimitry Andric 33406c3fb27SDimitry Andric IgnoreObjectResult IgnoreObject(const void *p) { 33568d75effSDimitry Andric void *chunk = allocator.GetBlockBegin(p); 33668d75effSDimitry Andric if (!chunk || p < chunk) return kIgnoreObjectInvalid; 33768d75effSDimitry Andric ChunkMetadata *m = Metadata(chunk); 33868d75effSDimitry Andric CHECK(m); 33968d75effSDimitry Andric if (m->allocated && (uptr)p < (uptr)chunk + m->requested_size) { 34068d75effSDimitry Andric if (m->tag == kIgnored) 34168d75effSDimitry Andric return kIgnoreObjectAlreadyIgnored; 34268d75effSDimitry Andric m->tag = kIgnored; 34368d75effSDimitry Andric return kIgnoreObjectSuccess; 34468d75effSDimitry Andric } else { 34568d75effSDimitry Andric return kIgnoreObjectInvalid; 34668d75effSDimitry Andric } 34768d75effSDimitry Andric } 348e8d8bef9SDimitry Andric 34968d75effSDimitry Andric } // namespace __lsan 35068d75effSDimitry Andric 35168d75effSDimitry Andric using namespace __lsan; 35268d75effSDimitry Andric 35368d75effSDimitry Andric extern "C" { 35468d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 35568d75effSDimitry Andric uptr __sanitizer_get_current_allocated_bytes() { 35668d75effSDimitry Andric uptr stats[AllocatorStatCount]; 35768d75effSDimitry Andric allocator.GetStats(stats); 35868d75effSDimitry Andric return stats[AllocatorStatAllocated]; 35968d75effSDimitry Andric } 36068d75effSDimitry Andric 36168d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 36268d75effSDimitry Andric uptr __sanitizer_get_heap_size() { 36368d75effSDimitry Andric uptr stats[AllocatorStatCount]; 36468d75effSDimitry Andric allocator.GetStats(stats); 36568d75effSDimitry Andric return stats[AllocatorStatMapped]; 36668d75effSDimitry Andric } 36768d75effSDimitry Andric 36868d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 36906c3fb27SDimitry Andric uptr __sanitizer_get_free_bytes() { return 1; } 37068d75effSDimitry Andric 37168d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 37268d75effSDimitry Andric uptr __sanitizer_get_unmapped_bytes() { return 0; } 37368d75effSDimitry Andric 37468d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 37568d75effSDimitry Andric uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; } 37668d75effSDimitry Andric 37768d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 37806c3fb27SDimitry Andric int __sanitizer_get_ownership(const void *p) { 37906c3fb27SDimitry Andric return GetMallocBegin(p) != nullptr; 38006c3fb27SDimitry Andric } 38106c3fb27SDimitry Andric 38206c3fb27SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 38306c3fb27SDimitry Andric const void * __sanitizer_get_allocated_begin(const void *p) { 38406c3fb27SDimitry Andric return GetMallocBegin(p); 38506c3fb27SDimitry Andric } 38668d75effSDimitry Andric 38768d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 38868d75effSDimitry Andric uptr __sanitizer_get_allocated_size(const void *p) { 38968d75effSDimitry Andric return GetMallocUsableSize(p); 39068d75effSDimitry Andric } 39168d75effSDimitry Andric 39206c3fb27SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 39306c3fb27SDimitry Andric uptr __sanitizer_get_allocated_size_fast(const void *p) { 39406c3fb27SDimitry Andric DCHECK_EQ(p, __sanitizer_get_allocated_begin(p)); 39506c3fb27SDimitry Andric uptr ret = GetMallocUsableSizeFast(p); 39606c3fb27SDimitry Andric DCHECK_EQ(ret, __sanitizer_get_allocated_size(p)); 39706c3fb27SDimitry Andric return ret; 39806c3fb27SDimitry Andric } 39906c3fb27SDimitry Andric 40006c3fb27SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 40106c3fb27SDimitry Andric void __sanitizer_purge_allocator() { allocator.ForceReleaseToOS(); } 40206c3fb27SDimitry Andric 40368d75effSDimitry Andric } // extern "C" 404