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 @@ -72,11 +72,15 @@ void Init(s32 release_to_os_interval_ms) { uptr TotalSpaceSize = kSpaceSize + AdditionalSize(); if (kUsingConstantSpaceBeg) { + CHECK(IsAligned(kSpaceBeg, SizeClassMap::kMaxSize)); 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); @@ -220,7 +224,7 @@ // Test-only. void TestOnlyUnmap() { - UnmapWithCallbackOrDie(SpaceBeg(), kSpaceSize + AdditionalSize()); + UnmapWithCallbackOrDie((uptr)address_range.base(), address_range.size()); } static void FillMemoryProfile(uptr start, uptr rss, bool file, uptr *stats, 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_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp @@ -129,6 +129,16 @@ sandboxing_callback = f; } +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 SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_sandbox_on_notify, diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cpp --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cpp +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_allocator_test.cpp @@ -1009,7 +1009,7 @@ // Don't test OOM conditions on Win64 because it causes other tests on the same // machine to OOM. #if SANITIZER_CAN_USE_ALLOCATOR64 && !SANITIZER_WINDOWS64 && !SANITIZER_ANDROID -typedef __sanitizer::SizeClassMap<3, 4, 8, 63, 128, 16> SpecialSizeClassMap; +typedef __sanitizer::SizeClassMap<3, 4, 8, 38, 128, 16> SpecialSizeClassMap; template struct AP64_SpecialSizeClassMap { static const uptr kSpaceBeg = kAllocatorSpace; 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; +}