1 // Copyright 2018 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "partition_alloc/shim/winheap_stubs_win.h"
6 
7 #include <bit>
8 
9 #include "partition_alloc/partition_alloc_base/bits.h"
10 #include "partition_alloc/partition_alloc_check.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 
13 namespace allocator_shim {
14 namespace {
15 
IsPtrAligned(void * ptr,size_t alignment)16 bool IsPtrAligned(void* ptr, size_t alignment) {
17   PA_CHECK(std::has_single_bit(alignment));
18   uintptr_t address = reinterpret_cast<uintptr_t>(ptr);
19   return partition_alloc::internal::base::bits::AlignUp(address, alignment) ==
20          address;
21 }
22 
23 }  // namespace
24 
TEST(WinHeapStubs,AlignedAllocationAreAligned)25 TEST(WinHeapStubs, AlignedAllocationAreAligned) {
26   for (size_t alignment = 1; alignment < 65536; alignment *= 2) {
27     SCOPED_TRACE(alignment);
28 
29     void* ptr = WinHeapAlignedMalloc(10, alignment);
30     ASSERT_NE(ptr, nullptr);
31     EXPECT_TRUE(IsPtrAligned(ptr, alignment));
32 
33     ptr = WinHeapAlignedRealloc(ptr, 1000, alignment);
34     ASSERT_NE(ptr, nullptr);
35     EXPECT_TRUE(IsPtrAligned(ptr, alignment));
36 
37     WinHeapAlignedFree(ptr);
38   }
39 }
40 
TEST(WinHeapStubs,AlignedReallocationsCorrectlyCopyData)41 TEST(WinHeapStubs, AlignedReallocationsCorrectlyCopyData) {
42   constexpr size_t kAlignment = 64;
43   constexpr uint8_t kMagicByte = 0xab;
44 
45   size_t old_size = 8;
46   void* ptr = WinHeapAlignedMalloc(old_size, kAlignment);
47   ASSERT_NE(ptr, nullptr);
48 
49   // Cause allocations to grow and shrink and confirm allocation contents are
50   // copied regardless.
51   constexpr size_t kSizes[] = {10, 1000, 50, 3000, 30, 9000};
52 
53   for (size_t size : kSizes) {
54     SCOPED_TRACE(size);
55 
56     memset(ptr, kMagicByte, old_size);
57     ptr = WinHeapAlignedRealloc(ptr, size, kAlignment);
58     ASSERT_NE(ptr, nullptr);
59 
60     for (size_t i = 0; i < std::min(size, old_size); i++) {
61       SCOPED_TRACE(i);
62       ASSERT_EQ(reinterpret_cast<uint8_t*>(ptr)[i], kMagicByte);
63     }
64 
65     old_size = size;
66   }
67 
68   WinHeapAlignedFree(ptr);
69 }
70 
71 }  // namespace allocator_shim
72