blob: 5d46f0f92a2d52cffbf4768150490adee80b3081 [file] [log] [blame]
Haibo Huang49cc9302020-04-27 16:14:24 -07001// 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 THIRD_PARTY_BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_FREELIST_ENTRY_H_
6#define THIRD_PARTY_BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_FREELIST_ENTRY_H_
7
8#include <stdint.h>
9
10#include "build/build_config.h"
11#include "third_party/base/allocator/partition_allocator/partition_alloc_constants.h"
12#include "third_party/base/compiler_specific.h"
13#include "third_party/base/sys_byteorder.h"
14
15namespace pdfium {
16namespace base {
17namespace internal {
18
19struct EncodedPartitionFreelistEntry;
20
21struct PartitionFreelistEntry {
22 EncodedPartitionFreelistEntry* next;
23
24 PartitionFreelistEntry() = delete;
25 ~PartitionFreelistEntry() = delete;
26
27 ALWAYS_INLINE static EncodedPartitionFreelistEntry* Encode(
28 PartitionFreelistEntry* ptr) {
29 return reinterpret_cast<EncodedPartitionFreelistEntry*>(Transform(ptr));
30 }
31
32 private:
33 friend struct EncodedPartitionFreelistEntry;
34 static ALWAYS_INLINE void* Transform(void* ptr) {
35 // We use bswap on little endian as a fast mask for two reasons:
36 // 1) If an object is freed and its vtable used where the attacker doesn't
37 // get the chance to run allocations between the free and use, the vtable
38 // dereference is likely to fault.
39 // 2) If the attacker has a linear buffer overflow and elects to try and
40 // corrupt a freelist pointer, partial pointer overwrite attacks are
41 // thwarted.
42 // For big endian, similar guarantees are arrived at with a negation.
43#if defined(ARCH_CPU_BIG_ENDIAN)
44 uintptr_t masked = ~reinterpret_cast<uintptr_t>(ptr);
45#else
46 uintptr_t masked = ByteSwapUintPtrT(reinterpret_cast<uintptr_t>(ptr));
47#endif
48 return reinterpret_cast<void*>(masked);
49 }
50};
51
52struct EncodedPartitionFreelistEntry {
53 char scrambled[sizeof(PartitionFreelistEntry*)];
54
55 EncodedPartitionFreelistEntry() = delete;
56 ~EncodedPartitionFreelistEntry() = delete;
57
58 ALWAYS_INLINE static PartitionFreelistEntry* Decode(
59 EncodedPartitionFreelistEntry* ptr) {
60 return reinterpret_cast<PartitionFreelistEntry*>(
61 PartitionFreelistEntry::Transform(ptr));
62 }
63};
64
65static_assert(sizeof(PartitionFreelistEntry) ==
66 sizeof(EncodedPartitionFreelistEntry),
67 "Should not have padding");
68
69} // namespace internal
70} // namespace base
71} // namespace pdfium
72
73#endif // THIRD_PARTY_BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_FREELIST_ENTRY_H_