| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2003 Apple Computer, Inc. | |
| 3 * Copyright (C) Research In Motion Limited 2010. All rights reserved. | |
| 4 * | |
| 5 * Portions are Copyright (C) 1998 Netscape Communications Corporation. | |
| 6 * | |
| 7 * This library is free software; you can redistribute it and/or | |
| 8 * modify it under the terms of the GNU Lesser General Public | |
| 9 * License as published by the Free Software Foundation; either | |
| 10 * version 2.1 of the License, or (at your option) any later version. | |
| 11 * | |
| 12 * This library is distributed in the hope that it will be useful, | |
| 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 15 * Lesser General Public License for more details. | |
| 16 * | |
| 17 * You should have received a copy of the GNU Lesser General Public | |
| 18 * License along with this library; if not, write to the Free Software | |
| 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 US
A | |
| 20 * | |
| 21 * Alternatively, the contents of this file may be used under the terms | |
| 22 * of either the Mozilla Public License Version 1.1, found at | |
| 23 * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public | |
| 24 * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html | |
| 25 * (the "GPL"), in which case the provisions of the MPL or the GPL are | |
| 26 * applicable instead of those above. If you wish to allow use of your | |
| 27 * version of this file only under the terms of one of those two | |
| 28 * licenses (the MPL or the GPL) and not to allow others to use your | |
| 29 * version of this file under the LGPL, indicate your decision by | |
| 30 * deletingthe provisions above and replace them with the notice and | |
| 31 * other provisions required by the MPL or the GPL, as the case may be. | |
| 32 * If you do not delete the provisions above, a recipient may use your | |
| 33 * version of this file under any of the LGPL, the MPL or the GPL. | |
| 34 */ | |
| 35 | |
| 36 #include "config.h" | |
| 37 #include "core/rendering/RenderArena.h" | |
| 38 | |
| 39 #include <stdlib.h> | |
| 40 #include <string.h> | |
| 41 | |
| 42 #include <limits> | |
| 43 | |
| 44 #include "wtf/Assertions.h" | |
| 45 #include "wtf/CryptographicallyRandomNumber.h" | |
| 46 | |
| 47 #define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y)) | |
| 48 | |
| 49 #ifdef NDEBUG | |
| 50 static void* MaskPtr(void* p, uintptr_t mask) | |
| 51 { | |
| 52 return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(p) ^ mask); | |
| 53 } | |
| 54 #endif | |
| 55 | |
| 56 namespace WebCore { | |
| 57 | |
| 58 #ifndef NDEBUG | |
| 59 | |
| 60 const int signature = 0xDBA00AEA; | |
| 61 const int signatureDead = 0xDBA00AED; | |
| 62 | |
| 63 typedef struct { | |
| 64 RenderArena* arena; | |
| 65 size_t size; | |
| 66 int signature; | |
| 67 } RenderArenaDebugHeader; | |
| 68 | |
| 69 static const size_t debugHeaderSize = ARENA_ALIGN(sizeof(RenderArenaDebugHeader)
); | |
| 70 | |
| 71 #endif | |
| 72 | |
| 73 RenderArena::RenderArena(unsigned arenaSize) | |
| 74 : m_totalSize(0) | |
| 75 , m_totalAllocated(0) | |
| 76 { | |
| 77 ASSERT(arenaSize > sizeof(Arena) + ARENA_ALIGN_MASK); | |
| 78 // The underlying Arena class allocates some metadata on top of our | |
| 79 // requested size. Factor this in so that we can get perfect power-of-two | |
| 80 // allocation sizes passed to the underlying malloc() call. | |
| 81 arenaSize -= (sizeof(Arena) + ARENA_ALIGN_MASK); | |
| 82 // Initialize the arena pool | |
| 83 INIT_ARENA_POOL(&m_pool, "RenderArena", arenaSize); | |
| 84 | |
| 85 // Zero out the recyclers array | |
| 86 memset(m_recyclers, 0, sizeof(m_recyclers)); | |
| 87 | |
| 88 // Mask freelist pointers to detect corruption and stop freelist spraying. | |
| 89 // We use an arbitray function and rely on ASLR to randomize it. | |
| 90 // The first value in RenderObject (or any class) is a vtable pointer, which | |
| 91 // always overlaps with the next pointer. This change guarantees that the | |
| 92 // masked vtable/next pointer will never point to valid memory. So, we | |
| 93 // should immediately crash on the first invalid vtable access for a stale | |
| 94 // RenderObject pointer. | |
| 95 // See http://download.crowdstrike.com/papers/hes-exploiting-a-coalmine.pdf. | |
| 96 WTF::cryptographicallyRandomValues(&m_mask, sizeof(m_mask)); | |
| 97 m_mask |= (static_cast<uintptr_t>(3) << (std::numeric_limits<uintptr_t>::dig
its - 2)) | 1; | |
| 98 } | |
| 99 | |
| 100 RenderArena::~RenderArena() | |
| 101 { | |
| 102 FinishArenaPool(&m_pool); | |
| 103 } | |
| 104 | |
| 105 void* RenderArena::allocate(size_t size) | |
| 106 { | |
| 107 ASSERT(size <= gMaxRecycledSize - 32); | |
| 108 m_totalSize += size; | |
| 109 | |
| 110 #ifdef ADDRESS_SANITIZER | |
| 111 return ::malloc(size); | |
| 112 #elif !defined(NDEBUG) | |
| 113 // Use standard malloc so that memory debugging tools work. | |
| 114 ASSERT(this); | |
| 115 void* block = ::malloc(debugHeaderSize + size); | |
| 116 RenderArenaDebugHeader* header = static_cast<RenderArenaDebugHeader*>(block)
; | |
| 117 header->arena = this; | |
| 118 header->size = size; | |
| 119 header->signature = signature; | |
| 120 return static_cast<char*>(block) + debugHeaderSize; | |
| 121 #else | |
| 122 // Ensure we have correct alignment for pointers. Important for Tru64 | |
| 123 size = ROUNDUP(size, sizeof(void*)); | |
| 124 | |
| 125 const size_t index = size >> kRecyclerShift; | |
| 126 | |
| 127 void* result = m_recyclers[index]; | |
| 128 if (result) { | |
| 129 // Need to move to the next object | |
| 130 void* next = MaskPtr(*((void**)result), m_mask); | |
| 131 m_recyclers[index] = next; | |
| 132 } | |
| 133 | |
| 134 if (!result) { | |
| 135 // Allocate a new chunk from the arena | |
| 136 unsigned bytesAllocated = 0; | |
| 137 ARENA_ALLOCATE(result, &m_pool, size, &bytesAllocated); | |
| 138 m_totalAllocated += bytesAllocated; | |
| 139 } | |
| 140 | |
| 141 return result; | |
| 142 #endif | |
| 143 } | |
| 144 | |
| 145 void RenderArena::free(size_t size, void* ptr) | |
| 146 { | |
| 147 ASSERT(size <= gMaxRecycledSize - 32); | |
| 148 m_totalSize -= size; | |
| 149 | |
| 150 #ifdef ADDRESS_SANITIZER | |
| 151 ::free(ptr); | |
| 152 #elif !defined(NDEBUG) | |
| 153 // Use standard free so that memory debugging tools work. | |
| 154 void* block = static_cast<char*>(ptr) - debugHeaderSize; | |
| 155 RenderArenaDebugHeader* header = static_cast<RenderArenaDebugHeader*>(block)
; | |
| 156 ASSERT(header->signature == signature); | |
| 157 ASSERT_UNUSED(size, header->size == size); | |
| 158 ASSERT(header->arena == this); | |
| 159 header->signature = signatureDead; | |
| 160 ::free(block); | |
| 161 #else | |
| 162 // Ensure we have correct alignment for pointers. Important for Tru64 | |
| 163 size = ROUNDUP(size, sizeof(void*)); | |
| 164 | |
| 165 const size_t index = size >> kRecyclerShift; | |
| 166 void* currentTop = m_recyclers[index]; | |
| 167 m_recyclers[index] = ptr; | |
| 168 *((void**)ptr) = MaskPtr(currentTop, m_mask); | |
| 169 #endif | |
| 170 } | |
| 171 | |
| 172 } // namespace WebCore | |
| OLD | NEW |