diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h @@ -75,8 +75,11 @@ CHECK_EQ(kSpaceBeg, address_range.Init(TotalSpaceSize, PrimaryAllocatorName, kSpaceBeg)); } else { - NonConstSpaceBeg = address_range.Init(TotalSpaceSize, - PrimaryAllocatorName); + // Combined allocator expects that an 2^N allocation is always aligned to + // 2^N. For this to work, the start of the space needs to be aligned as + // high as the largest size class (which also needs to be a power of 2). + NonConstSpaceBeg = address_range.InitAligned( + TotalSpaceSize, SizeClassMap::kMaxSize, PrimaryAllocatorName); CHECK_NE(NonConstSpaceBeg, ~(uptr)0); } SetReleaseToOSIntervalMs(release_to_os_interval_ms); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -143,6 +143,7 @@ class ReservedAddressRange { public: uptr Init(uptr size, const char *name = nullptr, uptr fixed_addr = 0); + uptr InitAligned(uptr size, uptr align, const char *name = nullptr); uptr Map(uptr fixed_addr, uptr size, const char *name = nullptr); uptr MapOrDie(uptr fixed_addr, uptr size, const char *name = nullptr); void Unmap(uptr addr, uptr size); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp @@ -323,6 +323,16 @@ return 0; } +uptr ReservedAddressRange::InitAligned(uptr size, uptr align, + const char *name) { + CHECK(IsPowerOfTwo(align)); + if (align <= GetPageSizeCached()) + return Init(size, name); + uptr start = Init(size + align, name); + start += align - (start & (align - 1)); + return start; +} + } // namespace __sanitizer using namespace __sanitizer; diff --git a/compiler-rt/test/hwasan/TestCases/malloc-align.c b/compiler-rt/test/hwasan/TestCases/malloc-align.c new file mode 100644 --- /dev/null +++ b/compiler-rt/test/hwasan/TestCases/malloc-align.c @@ -0,0 +1,37 @@ +// Test malloc alignment. +// RUN: %clang_hwasan -mllvm -hwasan-globals=0 %s -o %t +// RUN: %run %t + +#include +#include +#include +#include +#include + +static const size_t sizes[] = { + 1, 3, 7, 8, 9, 16, 17, 31, 32, 33, + 63, 64, 65, 127, 128, 129, 511, 512, 513, 2047, + 2048, 2049, 65535, 65536, 65537, 1048575, 1048576, 1048577}; +static const size_t alignments[] = {8, 16, 64, 256, 1024, 4096, 65536, 131072}; + +__attribute__((no_sanitize("hwaddress"))) int main() { + for (unsigned i = 0; i < sizeof(sizes) / sizeof(*sizes); ++i) { + for (unsigned j = 0; j < sizeof(alignments) / sizeof(*alignments); ++j) { + size_t size = sizes[i]; + size_t alignment = alignments[j]; + fprintf(stderr, "size %zu, alignment %zu (0x%zx)\n", size, alignment, + alignment); + const int cnt = 10; + void *ptrs[cnt]; + for (int k = 0; k < cnt; ++k) { + int res = posix_memalign(&ptrs[k], alignment, size); + assert(res == 0); + fprintf(stderr, "... addr 0x%zx\n", (size_t)ptrs[k]); + assert(((size_t)ptrs[k] & (alignment - 1)) == 0); + } + for (int k = 0; k < cnt; ++k) + free(ptrs[k]); + } + } + return 0; +}