summaryrefslogtreecommitdiffstats
path: root/build/build-clang/llvmorg-17-init-6897-g415b1cfd57de.patch
diff options
context:
space:
mode:
Diffstat (limited to 'build/build-clang/llvmorg-17-init-6897-g415b1cfd57de.patch')
-rw-r--r--build/build-clang/llvmorg-17-init-6897-g415b1cfd57de.patch395
1 files changed, 395 insertions, 0 deletions
diff --git a/build/build-clang/llvmorg-17-init-6897-g415b1cfd57de.patch b/build/build-clang/llvmorg-17-init-6897-g415b1cfd57de.patch
new file mode 100644
index 0000000000..596e32e56e
--- /dev/null
+++ b/build/build-clang/llvmorg-17-init-6897-g415b1cfd57de.patch
@@ -0,0 +1,395 @@
+From 415b1cfd57de62da8af9ad8dc567fc9d918dbaa5 Mon Sep 17 00:00:00 2001
+From: Thurston Dang <thurston@google.com>
+Date: Mon, 3 Apr 2023 21:14:40 +0000
+Subject: [PATCH] Add __sanitizer_get_allocated_begin API and implementations
+
+This function will return the start of the allocation, if given a pointer that lies within an allocation. Otherwise, it returns NULL.
+
+It will be useful for detecting dynamic TLS allocations in glibc >=2.25, which
+uses malloc (see https://github.com/google/sanitizers/issues/1409#issuecomment-1214244142).
+
+Reviewed By: vitalybuka
+
+Differential Revision: https://reviews.llvm.org/D147005
+---
+ .../include/sanitizer/allocator_interface.h | 4 ++
+ compiler-rt/lib/asan/asan_allocator.cpp | 15 +++++
+ compiler-rt/lib/dfsan/dfsan_allocator.cpp | 18 ++++++
+ compiler-rt/lib/hwasan/hwasan_allocator.cpp | 21 +++++++
+ compiler-rt/lib/lsan/lsan_allocator.cpp | 21 +++++++
+ compiler-rt/lib/memprof/memprof_allocator.cpp | 16 +++++
+ compiler-rt/lib/msan/msan_allocator.cpp | 19 ++++++
+ .../sanitizer_allocator_interface.h | 2 +
+ .../sanitizer_allocator_internal.h | 3 +-
+ .../sanitizer_common_interface.inc | 1 +
+ compiler-rt/lib/tsan/rtl/tsan_mman.cpp | 18 ++++++
+ .../TestCases/get_allocated_begin.cpp | 58 +++++++++++++++++++
+ 12 files changed, 195 insertions(+), 1 deletion(-)
+ create mode 100644 compiler-rt/test/sanitizer_common/TestCases/get_allocated_begin.cpp
+
+diff --git a/compiler-rt/include/sanitizer/allocator_interface.h b/compiler-rt/include/sanitizer/allocator_interface.h
+index 6226135ef84b3..d846f3f330741 100644
+--- a/compiler-rt/include/sanitizer/allocator_interface.h
++++ b/compiler-rt/include/sanitizer/allocator_interface.h
+@@ -26,6 +26,10 @@ extern "C" {
+ is not yet freed. */
+ int __sanitizer_get_ownership(const volatile void *p);
+
++ /* If a pointer lies within an allocation, it will return the start address
++ of the allocation. Otherwise, it returns nullptr. */
++ void *__sanitizer_get_allocated_begin(const void *p);
++
+ /* Returns the number of bytes reserved for the pointer p.
+ Requires (get_ownership(p) == true) or (p == 0). */
+ size_t __sanitizer_get_allocated_size(const volatile void *p);
+diff --git a/compiler-rt/lib/asan/asan_allocator.cpp b/compiler-rt/lib/asan/asan_allocator.cpp
+index 4c52a45b875c7..4b65b44a88f91 100644
+--- a/compiler-rt/lib/asan/asan_allocator.cpp
++++ b/compiler-rt/lib/asan/asan_allocator.cpp
+@@ -1164,6 +1164,17 @@ IgnoreObjectResult IgnoreObjectLocked(const void *p) {
+ // ---------------------- Interface ---------------- {{{1
+ using namespace __asan;
+
++void *AllocationBegin(const void *p) {
++ AsanChunk *m = __asan::instance.GetAsanChunkByAddr((uptr)p);
++ if (!m)
++ return nullptr;
++ if (atomic_load(&m->chunk_state, memory_order_acquire) != CHUNK_ALLOCATED)
++ return nullptr;
++ if (m->UsedSize() == 0)
++ return nullptr;
++ return (void *)(m->Beg());
++}
++
+ // ASan allocator doesn't reserve extra bytes, so normally we would
+ // just return "size". We don't want to expose our redzone sizes, etc here.
+ uptr __sanitizer_get_estimated_allocated_size(uptr size) {
+@@ -1187,6 +1198,10 @@ uptr __sanitizer_get_allocated_size(const void *p) {
+ return allocated_size;
+ }
+
++void *__sanitizer_get_allocated_begin(const void *p) {
++ return AllocationBegin(p);
++}
++
+ void __sanitizer_purge_allocator() {
+ GET_STACK_TRACE_MALLOC;
+ instance.Purge(&stack);
+diff --git a/compiler-rt/lib/dfsan/dfsan_allocator.cpp b/compiler-rt/lib/dfsan/dfsan_allocator.cpp
+index 5fb8fef213b9a..cebf9983c9490 100644
+--- a/compiler-rt/lib/dfsan/dfsan_allocator.cpp
++++ b/compiler-rt/lib/dfsan/dfsan_allocator.cpp
+@@ -174,6 +174,20 @@ void *DFsanCalloc(uptr nmemb, uptr size) {
+ return DFsanAllocate(nmemb * size, sizeof(u64), true /*zeroise*/);
+ }
+
++void *AllocationBegin(const void *p) {
++ if (!p)
++ return nullptr;
++ const void *beg = allocator.GetBlockBegin(p);
++ if (!beg)
++ return nullptr;
++ Metadata *b = (Metadata *)allocator.GetMetaData(beg);
++ if (!b)
++ return nullptr;
++ if (b->requested_size == 0)
++ return nullptr;
++ return (void *)beg;
++}
++
+ static uptr AllocationSize(const void *p) {
+ if (!p)
+ return 0;
+@@ -294,4 +308,8 @@ uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; }
+
+ int __sanitizer_get_ownership(const void *p) { return AllocationSize(p) != 0; }
+
++void *__sanitizer_get_allocated_begin(const void *p) {
++ return AllocationBegin(p);
++}
++
+ uptr __sanitizer_get_allocated_size(const void *p) { return AllocationSize(p); }
+diff --git a/compiler-rt/lib/hwasan/hwasan_allocator.cpp b/compiler-rt/lib/hwasan/hwasan_allocator.cpp
+index d096a8faa2c7e..8ccdeb23fa995 100644
+--- a/compiler-rt/lib/hwasan/hwasan_allocator.cpp
++++ b/compiler-rt/lib/hwasan/hwasan_allocator.cpp
+@@ -397,6 +397,23 @@ HwasanChunkView FindHeapChunkByAddress(uptr address) {
+ return HwasanChunkView(reinterpret_cast<uptr>(block), metadata);
+ }
+
++void *AllocationBegin(const void *p) {
++ const void *untagged_ptr = UntagPtr(p);
++ if (!untagged_ptr)
++ return nullptr;
++
++ const void *beg = allocator.GetBlockBegin(untagged_ptr);
++ if (!beg)
++ return nullptr;
++
++ Metadata *b = (Metadata *)allocator.GetMetaData(beg);
++ if (b->GetRequestedSize() == 0)
++ return nullptr;
++
++ tag_t tag = GetTagFromPointer((uptr)p);
++ return (void *)AddTagToPointer((uptr)beg, tag);
++}
++
+ static uptr AllocationSize(const void *tagged_ptr) {
+ const void *untagged_ptr = UntagPtr(tagged_ptr);
+ if (!untagged_ptr) return 0;
+@@ -641,4 +658,8 @@ uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; }
+
+ int __sanitizer_get_ownership(const void *p) { return AllocationSize(p) != 0; }
+
++void *__sanitizer_get_allocated_begin(const void *p) {
++ return AllocationBegin(p);
++}
++
+ uptr __sanitizer_get_allocated_size(const void *p) { return AllocationSize(p); }
+diff --git a/compiler-rt/lib/lsan/lsan_allocator.cpp b/compiler-rt/lib/lsan/lsan_allocator.cpp
+index 37ba363d479dd..d50882657dc33 100644
+--- a/compiler-rt/lib/lsan/lsan_allocator.cpp
++++ b/compiler-rt/lib/lsan/lsan_allocator.cpp
+@@ -145,6 +145,22 @@ void GetAllocatorCacheRange(uptr *begin, uptr *end) {
+ *end = *begin + sizeof(AllocatorCache);
+ }
+
++void *GetMallocBegin(const void *p) {
++ if (!p)
++ return nullptr;
++ const void *beg = allocator.GetBlockBegin(p);
++ if (!beg)
++ return nullptr;
++ ChunkMetadata *m = Metadata(beg);
++ if (!m)
++ return nullptr;
++ if (!m->allocated)
++ return nullptr;
++ if (m->requested_size == 0)
++ return nullptr;
++ return (void *)beg;
++}
++
+ uptr GetMallocUsableSize(const void *p) {
+ if (!p)
+ return 0;
+@@ -363,6 +379,11 @@ uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; }
+ SANITIZER_INTERFACE_ATTRIBUTE
+ int __sanitizer_get_ownership(const void *p) { return Metadata(p) != nullptr; }
+
++SANITIZER_INTERFACE_ATTRIBUTE
++void * __sanitizer_get_allocated_begin(const void *p) {
++ return GetMallocBegin(p);
++}
++
+ SANITIZER_INTERFACE_ATTRIBUTE
+ uptr __sanitizer_get_allocated_size(const void *p) {
+ return GetMallocUsableSize(p);
+diff --git a/compiler-rt/lib/memprof/memprof_allocator.cpp b/compiler-rt/lib/memprof/memprof_allocator.cpp
+index 51c3a66ebd680..80a87d49dfc6e 100644
+--- a/compiler-rt/lib/memprof/memprof_allocator.cpp
++++ b/compiler-rt/lib/memprof/memprof_allocator.cpp
+@@ -681,6 +681,18 @@ int memprof_posix_memalign(void **memptr, uptr alignment, uptr size,
+ return 0;
+ }
+
++void *memprof_malloc_begin(const void *p) {
++ u64 user_requested_size;
++ MemprofChunk *m =
++ instance.GetMemprofChunkByAddr((uptr)p, user_requested_size);
++ if (!m)
++ return nullptr;
++ if (user_requested_size == 0)
++ return nullptr;
++
++ return (void *)m->Beg();
++}
++
+ uptr memprof_malloc_usable_size(const void *ptr, uptr pc, uptr bp) {
+ if (!ptr)
+ return 0;
+@@ -699,6 +711,10 @@ int __sanitizer_get_ownership(const void *p) {
+ return memprof_malloc_usable_size(p, 0, 0) != 0;
+ }
+
++void *__sanitizer_get_allocated_begin(const void *p) {
++ return memprof_malloc_begin(p);
++}
++
+ uptr __sanitizer_get_allocated_size(const void *p) {
+ return memprof_malloc_usable_size(p, 0, 0);
+ }
+diff --git a/compiler-rt/lib/msan/msan_allocator.cpp b/compiler-rt/lib/msan/msan_allocator.cpp
+index 3308ee7053a61..a760a434158a5 100644
+--- a/compiler-rt/lib/msan/msan_allocator.cpp
++++ b/compiler-rt/lib/msan/msan_allocator.cpp
+@@ -260,6 +260,21 @@ static void *MsanCalloc(StackTrace *stack, uptr nmemb, uptr size) {
+ return MsanAllocate(stack, nmemb * size, sizeof(u64), true);
+ }
+
++void *AllocationBegin(const void *p) {
++ if (!p)
++ return nullptr;
++ const void *beg = allocator.GetBlockBegin(p);
++ if (!beg)
++ return nullptr;
++ Metadata *b = (Metadata *)allocator.GetMetaData(beg);
++ if (!b)
++ return nullptr;
++ if (b->requested_size == 0)
++ return nullptr;
++
++ return (void *)beg;
++}
++
+ static uptr AllocationSize(const void *p) {
+ if (!p) return 0;
+ const void *beg = allocator.GetBlockBegin(p);
+@@ -373,4 +388,8 @@ uptr __sanitizer_get_estimated_allocated_size(uptr size) { return size; }
+
+ int __sanitizer_get_ownership(const void *p) { return AllocationSize(p) != 0; }
+
++void *__sanitizer_get_allocated_begin(const void *p) {
++ return AllocationBegin(p);
++}
++
+ uptr __sanitizer_get_allocated_size(const void *p) { return AllocationSize(p); }
+diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_interface.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_interface.h
+index c1b27563e2fc7..35c7c97df3299 100644
+--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_interface.h
++++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_interface.h
+@@ -21,6 +21,8 @@ extern "C" {
+ SANITIZER_INTERFACE_ATTRIBUTE
+ uptr __sanitizer_get_estimated_allocated_size(uptr size);
+ SANITIZER_INTERFACE_ATTRIBUTE int __sanitizer_get_ownership(const void *p);
++SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void *
++__sanitizer_get_allocated_begin(const void *p);
+ SANITIZER_INTERFACE_ATTRIBUTE uptr
+ __sanitizer_get_allocated_size(const void *p);
+ SANITIZER_INTERFACE_ATTRIBUTE uptr __sanitizer_get_current_allocated_bytes();
+diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h
+index 38994736877ac..adbdad5a1ee0c 100644
+--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h
++++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_internal.h
+@@ -51,7 +51,8 @@ void InternalFree(void *p, InternalAllocatorCache *cache = nullptr);
+ void InternalAllocatorLock();
+ void InternalAllocatorUnlock();
+ InternalAllocator *internal_allocator();
+-
++int __sanitizer_get_allocation_bounds(const void *p, void **start,
++ unsigned long long *size);
+ } // namespace __sanitizer
+
+ #endif // SANITIZER_ALLOCATOR_INTERNAL_H
+diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc
+index 958f071e7b5f7..01be600e33ba3 100644
+--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc
++++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc
+@@ -32,6 +32,7 @@ INTERFACE_FUNCTION(__sanitizer_get_module_and_offset_for_pc)
+ INTERFACE_FUNCTION(__sanitizer_symbolize_global)
+ INTERFACE_FUNCTION(__sanitizer_symbolize_pc)
+ // Allocator interface.
++INTERFACE_FUNCTION(__sanitizer_get_allocated_begin)
+ INTERFACE_FUNCTION(__sanitizer_get_allocated_size)
+ INTERFACE_FUNCTION(__sanitizer_get_current_allocated_bytes)
+ INTERFACE_FUNCTION(__sanitizer_get_estimated_allocated_size)
+diff --git a/compiler-rt/lib/tsan/rtl/tsan_mman.cpp b/compiler-rt/lib/tsan/rtl/tsan_mman.cpp
+index 99fa492265615..9c548dfff91f3 100644
+--- a/compiler-rt/lib/tsan/rtl/tsan_mman.cpp
++++ b/compiler-rt/lib/tsan/rtl/tsan_mman.cpp
+@@ -352,6 +352,20 @@ void *user_pvalloc(ThreadState *thr, uptr pc, uptr sz) {
+ return SetErrnoOnNull(user_alloc_internal(thr, pc, sz, PageSize));
+ }
+
++void *user_alloc_begin(const void *p) {
++ if (p == nullptr || !IsAppMem((uptr)p))
++ return nullptr;
++ const void *beg = allocator()->GetBlockBegin(p);
++ if (!beg)
++ return nullptr;
++
++ MBlock *b = ctx->metamap.GetBlock((uptr)beg);
++ if (!b)
++ return nullptr; // Not a valid pointer.
++
++ return (void *)beg;
++}
++
+ uptr user_alloc_usable_size(const void *p) {
+ if (p == 0 || !IsAppMem((uptr)p))
+ return 0;
+@@ -430,6 +444,10 @@ int __sanitizer_get_ownership(const void *p) {
+ return allocator()->GetBlockBegin(p) != 0;
+ }
+
++void *__sanitizer_get_allocated_begin(const void *p) {
++ return user_alloc_begin(p);
++}
++
+ uptr __sanitizer_get_allocated_size(const void *p) {
+ return user_alloc_usable_size(p);
+ }
+diff --git a/compiler-rt/test/sanitizer_common/TestCases/get_allocated_begin.cpp b/compiler-rt/test/sanitizer_common/TestCases/get_allocated_begin.cpp
+new file mode 100644
+index 0000000000000..6892a4a7fb282
+--- /dev/null
++++ b/compiler-rt/test/sanitizer_common/TestCases/get_allocated_begin.cpp
+@@ -0,0 +1,58 @@
++// RUN: %clangxx -O0 -g %s -o %t && %run %t
++
++// UBSan does not have its own allocator
++// UNSUPPORTED: ubsan
++
++#include <assert.h>
++#include <sanitizer/allocator_interface.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++// Based on lib/msan/tests/msan_test.cpp::get_allocated_size_and_ownership
++int main(void) {
++ int sizes[] = {10, 100, 1000, 10000, 100000, 1000000};
++
++ for (int i = 0; i < sizeof(sizes) / sizeof(int); i++) {
++ printf("Testing size %d\n", sizes[i]);
++
++ char *array = reinterpret_cast<char *>(malloc(sizes[i]));
++ int *int_ptr = new int;
++ printf("array: %p\n", array);
++ printf("int_ptr: %p\n", int_ptr);
++
++ // Bogus value to unpoison start. Calling __sanitizer_get_allocated_begin
++ // does not unpoison it.
++ void *start = NULL;
++ for (int j = 0; j < sizes[i]; j++) {
++ printf("j: %d\n", j);
++
++ start = __sanitizer_get_allocated_begin(array + j);
++ printf("Start: %p (expected: %p)\n", start, array);
++ fflush(stdout);
++ assert(array == start);
++ }
++
++ start = __sanitizer_get_allocated_begin(int_ptr);
++ assert(int_ptr == start);
++
++ void *wild_addr = reinterpret_cast<void *>(4096 * 160);
++ assert(__sanitizer_get_allocated_begin(wild_addr) == NULL);
++
++ wild_addr = reinterpret_cast<void *>(0x1);
++ assert(__sanitizer_get_allocated_begin(wild_addr) == NULL);
++
++ // NULL is a valid argument for GetAllocatedSize but is not owned.
++ assert(__sanitizer_get_allocated_begin(NULL) == NULL);
++
++ free(array);
++ for (int j = 0; j < sizes[i]; j++) {
++ assert(__sanitizer_get_allocated_begin(array + j) == NULL);
++ }
++
++ delete int_ptr;
++ assert(__sanitizer_get_allocated_begin(int_ptr) == NULL);
++ }
++
++ return 0;
++}