1 // Copyright (c) 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_COOKIE_H_
6 #define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_COOKIE_H_
7 
8 #include "base/allocator/buildflags.h"
9 #include "base/allocator/partition_allocator/partition_alloc_check.h"
10 #include "base/compiler_specific.h"
11 
12 namespace base {
13 namespace internal {
14 
15 // Handles alignment up to XMM instructions on Intel.
16 static constexpr size_t kCookieSize = 16;
17 
18 // Cookies are enabled for debug builds.
19 #if DCHECK_IS_ON()
20 
21 static constexpr unsigned char kCookieValue[kCookieSize] = {
22     0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xD0, 0x0D,
23     0x13, 0x37, 0xF0, 0x05, 0xBA, 0x11, 0xAB, 0x1E};
24 
PartitionCookieCheckValue(void * ptr)25 ALWAYS_INLINE void PartitionCookieCheckValue(void* ptr) {
26   unsigned char* cookie_ptr = reinterpret_cast<unsigned char*>(ptr);
27   for (size_t i = 0; i < kCookieSize; ++i, ++cookie_ptr)
28     PA_DCHECK(*cookie_ptr == kCookieValue[i]);
29 }
30 
PartitionCookieSizeAdjustAdd(size_t size)31 ALWAYS_INLINE size_t PartitionCookieSizeAdjustAdd(size_t size) {
32   // Add space for cookies, checking for integer overflow. TODO(palmer):
33   // Investigate the performance and code size implications of using
34   // CheckedNumeric throughout PA.
35   PA_DCHECK(size + (2 * kCookieSize) > size);
36   size += 2 * kCookieSize;
37   return size;
38 }
39 
PartitionCookieSizeAdjustSubtract(size_t size)40 ALWAYS_INLINE size_t PartitionCookieSizeAdjustSubtract(size_t size) {
41   // Remove space for cookies.
42   PA_DCHECK(size >= 2 * kCookieSize);
43   size -= 2 * kCookieSize;
44   return size;
45 }
46 
PartitionCookiePointerAdjustSubtract(void * ptr)47 ALWAYS_INLINE void* PartitionCookiePointerAdjustSubtract(void* ptr) {
48   // The value given to the application is actually just after the cookie.
49   ptr = static_cast<char*>(ptr) - kCookieSize;
50   return ptr;
51 }
52 
PartitionCookiePointerAdjustAdd(void * ptr)53 ALWAYS_INLINE void* PartitionCookiePointerAdjustAdd(void* ptr) {
54   // The value given to the application is actually just after the cookie.
55   ptr = static_cast<char*>(ptr) + kCookieSize;
56   return ptr;
57 }
58 
PartitionCookieWriteValue(void * ptr)59 ALWAYS_INLINE void PartitionCookieWriteValue(void* ptr) {
60   unsigned char* cookie_ptr = reinterpret_cast<unsigned char*>(ptr);
61   for (size_t i = 0; i < kCookieSize; ++i, ++cookie_ptr)
62     *cookie_ptr = kCookieValue[i];
63 }
64 
65 #else
66 
PartitionCookieCheckValue(void * ptr)67 ALWAYS_INLINE void PartitionCookieCheckValue(void* ptr) {}
68 
PartitionCookieSizeAdjustAdd(size_t size)69 ALWAYS_INLINE size_t PartitionCookieSizeAdjustAdd(size_t size) {
70   return size;
71 }
72 
PartitionCookieSizeAdjustSubtract(size_t size)73 ALWAYS_INLINE size_t PartitionCookieSizeAdjustSubtract(size_t size) {
74   return size;
75 }
76 
PartitionCookiePointerAdjustSubtract(void * ptr)77 ALWAYS_INLINE void* PartitionCookiePointerAdjustSubtract(void* ptr) {
78   return ptr;
79 }
80 
PartitionCookiePointerAdjustAdd(void * ptr)81 ALWAYS_INLINE void* PartitionCookiePointerAdjustAdd(void* ptr) {
82   return ptr;
83 }
84 
PartitionCookieWriteValue(void * ptr)85 ALWAYS_INLINE void PartitionCookieWriteValue(void* ptr) {}
86 #endif  // DCHECK_IS_ON()
87 
88 }  // namespace internal
89 }  // namespace base
90 
91 #endif  // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_COOKIE_H_
92