| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 nonLargeObjectPageSizeMax >= blinkPageSize, | 167 nonLargeObjectPageSizeMax >= blinkPageSize, |
| 168 "max size supported by HeapObjectHeader must at least be blinkPageSize"); | 168 "max size supported by HeapObjectHeader must at least be blinkPageSize"); |
| 169 | 169 |
| 170 class PLATFORM_EXPORT HeapObjectHeader { | 170 class PLATFORM_EXPORT HeapObjectHeader { |
| 171 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); | 171 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); |
| 172 | 172 |
| 173 public: | 173 public: |
| 174 // If |gcInfoIndex| is 0, this header is interpreted as a free list header. | 174 // If |gcInfoIndex| is 0, this header is interpreted as a free list header. |
| 175 NO_SANITIZE_ADDRESS | 175 NO_SANITIZE_ADDRESS |
| 176 HeapObjectHeader(size_t size, size_t gcInfoIndex) { | 176 HeapObjectHeader(size_t size, size_t gcInfoIndex) { |
| 177 m_magic = getMagic(); | |
| 178 // sizeof(HeapObjectHeader) must be equal to or smaller than | 177 // sizeof(HeapObjectHeader) must be equal to or smaller than |
| 179 // |allocationGranularity|, because |HeapObjectHeader| is used as a header | 178 // |allocationGranularity|, because |HeapObjectHeader| is used as a header |
| 180 // for a freed entry. Given that the smallest entry size is | 179 // for a freed entry. Given that the smallest entry size is |
| 181 // |allocationGranurarity|, |HeapObjectHeader| must fit into the size. | 180 // |allocationGranurarity|, |HeapObjectHeader| must fit into the size. |
| 182 static_assert( | 181 static_assert( |
| 183 sizeof(HeapObjectHeader) <= allocationGranularity, | 182 sizeof(HeapObjectHeader) <= allocationGranularity, |
| 184 "size of HeapObjectHeader must be smaller than allocationGranularity"); | 183 "size of HeapObjectHeader must be smaller than allocationGranularity"); |
| 184 #if CPU(64BIT) |
| 185 static_assert(sizeof(HeapObjectHeader) == 8, | 185 static_assert(sizeof(HeapObjectHeader) == 8, |
| 186 "sizeof(HeapObjectHeader) must be 8 bytes"); | 186 "sizeof(HeapObjectHeader) must be 8 bytes"); |
| 187 m_magic = getMagic(); |
| 188 #endif |
| 187 | 189 |
| 188 ASSERT(gcInfoIndex < GCInfoTable::maxIndex); | 190 ASSERT(gcInfoIndex < GCInfoTable::maxIndex); |
| 189 ASSERT(size < nonLargeObjectPageSizeMax); | 191 ASSERT(size < nonLargeObjectPageSizeMax); |
| 190 ASSERT(!(size & allocationMask)); | 192 ASSERT(!(size & allocationMask)); |
| 191 m_encoded = static_cast<uint32_t>( | 193 m_encoded = static_cast<uint32_t>( |
| 192 (gcInfoIndex << headerGCInfoIndexShift) | size | | 194 (gcInfoIndex << headerGCInfoIndexShift) | size | |
| 193 (gcInfoIndex == gcInfoIndexForFreeListHeader ? headerFreedBitMask : 0)); | 195 (gcInfoIndex == gcInfoIndexForFreeListHeader ? headerFreedBitMask : 0)); |
| 194 } | 196 } |
| 195 | 197 |
| 196 NO_SANITIZE_ADDRESS | 198 NO_SANITIZE_ADDRESS |
| (...skipping 25 matching lines...) Expand all Loading... |
| 222 | 224 |
| 223 Address payload(); | 225 Address payload(); |
| 224 size_t payloadSize(); | 226 size_t payloadSize(); |
| 225 Address payloadEnd(); | 227 Address payloadEnd(); |
| 226 | 228 |
| 227 // TODO(633030): Make |checkHeader| and |zapMagic| private. This class should | 229 // TODO(633030): Make |checkHeader| and |zapMagic| private. This class should |
| 228 // manage its integrity on its own, without requiring outside callers to | 230 // manage its integrity on its own, without requiring outside callers to |
| 229 // explicitly check. | 231 // explicitly check. |
| 230 bool checkHeader() const; | 232 bool checkHeader() const; |
| 231 | 233 |
| 234 #if DCHECK_IS_ON() && CPU(64BIT) |
| 232 // Zap |m_magic| with a new magic number that means there was once an object | 235 // Zap |m_magic| with a new magic number that means there was once an object |
| 233 // allocated here, but it was freed because nobody marked it during GC. | 236 // allocated here, but it was freed because nobody marked it during GC. |
| 234 void zapMagic(); | 237 void zapMagic(); |
| 238 #endif |
| 235 | 239 |
| 236 void finalize(Address, size_t); | 240 void finalize(Address, size_t); |
| 237 static HeapObjectHeader* fromPayload(const void*); | 241 static HeapObjectHeader* fromPayload(const void*); |
| 238 | 242 |
| 239 static const uint32_t zappedMagic = 0xDEAD4321; | 243 static const uint32_t zappedMagic = 0xDEAD4321; |
| 240 | 244 |
| 241 private: | 245 private: |
| 246 #if CPU(64BIT) |
| 242 // Returns a random value. | 247 // Returns a random value. |
| 243 // | 248 // |
| 244 // The implementation gets its randomness from the locations of 2 independent | 249 // The implementation gets its randomness from the locations of 2 independent |
| 245 // sources of address space layout randomization: a function in a Chrome | 250 // sources of address space layout randomization: a function in a Chrome |
| 246 // executable image, and a function in an external DLL/so. This implementation | 251 // executable image, and a function in an external DLL/so. This implementation |
| 247 // should be fast and small, and should have the benefit of requiring | 252 // should be fast and small, and should have the benefit of requiring |
| 248 // attackers to discover and use 2 independent weak infoleak bugs, or 1 | 253 // attackers to discover and use 2 independent weak infoleak bugs, or 1 |
| 249 // arbitrary infoleak bug (used twice). | 254 // arbitrary infoleak bug (used twice). |
| 250 uint32_t getMagic() const; | 255 uint32_t getMagic() const; |
| 256 uint32_t m_magic; |
| 257 #endif |
| 251 | 258 |
| 252 uint32_t m_magic; | |
| 253 uint32_t m_encoded; | 259 uint32_t m_encoded; |
| 254 }; | 260 }; |
| 255 | 261 |
| 256 class FreeListEntry final : public HeapObjectHeader { | 262 class FreeListEntry final : public HeapObjectHeader { |
| 257 public: | 263 public: |
| 258 NO_SANITIZE_ADDRESS | 264 NO_SANITIZE_ADDRESS |
| 259 explicit FreeListEntry(size_t size) | 265 explicit FreeListEntry(size_t size) |
| 260 : HeapObjectHeader(size, gcInfoIndexForFreeListHeader), m_next(nullptr) { | 266 : HeapObjectHeader(size, gcInfoIndexForFreeListHeader), m_next(nullptr) { |
| 261 #if DCHECK_IS_ON() | 267 #if DCHECK_IS_ON() && CPU(64BIT) |
| 262 ASSERT(size >= sizeof(HeapObjectHeader)); | 268 ASSERT(size >= sizeof(HeapObjectHeader)); |
| 263 zapMagic(); | 269 zapMagic(); |
| 264 #endif | 270 #endif |
| 265 } | 271 } |
| 266 | 272 |
| 267 Address getAddress() { return reinterpret_cast<Address>(this); } | 273 Address getAddress() { return reinterpret_cast<Address>(this); } |
| 268 | 274 |
| 269 NO_SANITIZE_ADDRESS | 275 NO_SANITIZE_ADDRESS |
| 270 void unlink(FreeListEntry** prevNext) { | 276 void unlink(FreeListEntry** prevNext) { |
| 271 *prevNext = m_next; | 277 *prevNext = m_next; |
| (...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 826 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::size() const { | 832 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::size() const { |
| 827 size_t result = m_encoded & headerSizeMask; | 833 size_t result = m_encoded & headerSizeMask; |
| 828 // Large objects should not refer to header->size(). The actual size of a | 834 // Large objects should not refer to header->size(). The actual size of a |
| 829 // large object is stored in |LargeObjectPage::m_payloadSize|. | 835 // large object is stored in |LargeObjectPage::m_payloadSize|. |
| 830 ASSERT(result != largeObjectSizeInHeader); | 836 ASSERT(result != largeObjectSizeInHeader); |
| 831 ASSERT(!pageFromObject(this)->isLargeObjectPage()); | 837 ASSERT(!pageFromObject(this)->isLargeObjectPage()); |
| 832 return result; | 838 return result; |
| 833 } | 839 } |
| 834 | 840 |
| 835 NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::checkHeader() const { | 841 NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::checkHeader() const { |
| 842 #if CPU(64BIT) |
| 836 return m_magic == getMagic(); | 843 return m_magic == getMagic(); |
| 844 #else |
| 845 return true; |
| 846 #endif |
| 837 } | 847 } |
| 838 | 848 |
| 839 inline Address HeapObjectHeader::payload() { | 849 inline Address HeapObjectHeader::payload() { |
| 840 return reinterpret_cast<Address>(this) + sizeof(HeapObjectHeader); | 850 return reinterpret_cast<Address>(this) + sizeof(HeapObjectHeader); |
| 841 } | 851 } |
| 842 | 852 |
| 843 inline Address HeapObjectHeader::payloadEnd() { | 853 inline Address HeapObjectHeader::payloadEnd() { |
| 844 return reinterpret_cast<Address>(this) + size(); | 854 return reinterpret_cast<Address>(this) + size(); |
| 845 } | 855 } |
| 846 | 856 |
| 847 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::payloadSize() { | 857 NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::payloadSize() { |
| 848 size_t size = m_encoded & headerSizeMask; | 858 size_t size = m_encoded & headerSizeMask; |
| 849 if (UNLIKELY(size == largeObjectSizeInHeader)) { | 859 if (UNLIKELY(size == largeObjectSizeInHeader)) { |
| 850 ASSERT(pageFromObject(this)->isLargeObjectPage()); | 860 ASSERT(pageFromObject(this)->isLargeObjectPage()); |
| 851 return static_cast<LargeObjectPage*>(pageFromObject(this))->payloadSize(); | 861 return static_cast<LargeObjectPage*>(pageFromObject(this))->payloadSize(); |
| 852 } | 862 } |
| 853 ASSERT(!pageFromObject(this)->isLargeObjectPage()); | 863 ASSERT(!pageFromObject(this)->isLargeObjectPage()); |
| 854 return size - sizeof(HeapObjectHeader); | 864 return size - sizeof(HeapObjectHeader); |
| 855 } | 865 } |
| 856 | 866 |
| 857 inline HeapObjectHeader* HeapObjectHeader::fromPayload(const void* payload) { | 867 inline HeapObjectHeader* HeapObjectHeader::fromPayload(const void* payload) { |
| 858 Address addr = reinterpret_cast<Address>(const_cast<void*>(payload)); | 868 Address addr = reinterpret_cast<Address>(const_cast<void*>(payload)); |
| 859 HeapObjectHeader* header = | 869 HeapObjectHeader* header = |
| 860 reinterpret_cast<HeapObjectHeader*>(addr - sizeof(HeapObjectHeader)); | 870 reinterpret_cast<HeapObjectHeader*>(addr - sizeof(HeapObjectHeader)); |
| 861 ASSERT(header->checkHeader()); | 871 ASSERT(header->checkHeader()); |
| 862 return header; | 872 return header; |
| 863 } | 873 } |
| 864 | 874 |
| 875 #if CPU(64BIT) |
| 865 inline uint32_t HeapObjectHeader::getMagic() const { | 876 inline uint32_t HeapObjectHeader::getMagic() const { |
| 866 const uintptr_t random1 = | 877 const uintptr_t random1 = |
| 867 ~(reinterpret_cast<uintptr_t>( | 878 ~(reinterpret_cast<uintptr_t>( |
| 868 base::trace_event::MemoryAllocatorDump::kNameSize) >> | 879 base::trace_event::MemoryAllocatorDump::kNameSize) >> |
| 869 16); | 880 16); |
| 870 | 881 |
| 871 #if OS(WIN) | 882 #if OS(WIN) |
| 872 const uintptr_t random2 = ~(reinterpret_cast<uintptr_t>(::ReadFile) << 16); | 883 const uintptr_t random2 = ~(reinterpret_cast<uintptr_t>(::ReadFile) << 16); |
| 873 #elif OS(POSIX) | 884 #elif OS(POSIX) |
| 874 const uintptr_t random2 = ~(reinterpret_cast<uintptr_t>(::read) << 16); | 885 const uintptr_t random2 = ~(reinterpret_cast<uintptr_t>(::read) << 16); |
| 875 #else | 886 #else |
| 876 #error OS not supported | 887 #error OS not supported |
| 877 #endif | 888 #endif |
| 878 | 889 |
| 879 #if CPU(64BIT) | 890 #if CPU(64BIT) |
| 880 static_assert(sizeof(uintptr_t) == sizeof(uint64_t), | 891 static_assert(sizeof(uintptr_t) == sizeof(uint64_t), |
| 881 "uintptr_t is not uint64_t"); | 892 "uintptr_t is not uint64_t"); |
| 882 const uint32_t random = static_cast<uint32_t>( | 893 const uint32_t random = static_cast<uint32_t>( |
| 883 (random1 & 0x0FFFFULL) | ((random2 >> 32) & 0x0FFFF0000ULL)); | 894 (random1 & 0x0FFFFULL) | ((random2 >> 32) & 0x0FFFF0000ULL)); |
| 884 #elif CPU(32BIT) | 895 #elif CPU(32BIT) |
| 896 // Although we don't use heap metadata canaries on 32-bit due to memory |
| 897 // pressure, keep this code around just in case we do, someday. |
| 885 static_assert(sizeof(uintptr_t) == sizeof(uint32_t), | 898 static_assert(sizeof(uintptr_t) == sizeof(uint32_t), |
| 886 "uintptr_t is not uint32_t"); | 899 "uintptr_t is not uint32_t"); |
| 887 const uint32_t random = (random1 & 0x0FFFFUL) | (random2 & 0xFFFF0000UL); | 900 const uint32_t random = (random1 & 0x0FFFFUL) | (random2 & 0xFFFF0000UL); |
| 888 #else | 901 #else |
| 889 #error architecture not supported | 902 #error architecture not supported |
| 890 #endif | 903 #endif |
| 891 | 904 |
| 892 return random; | 905 return random; |
| 893 } | 906 } |
| 907 #endif |
| 894 | 908 |
| 895 NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::isWrapperHeaderMarked() | 909 NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::isWrapperHeaderMarked() |
| 896 const { | 910 const { |
| 897 ASSERT(checkHeader()); | 911 ASSERT(checkHeader()); |
| 898 return m_encoded & headerWrapperMarkBitMask; | 912 return m_encoded & headerWrapperMarkBitMask; |
| 899 } | 913 } |
| 900 | 914 |
| 901 NO_SANITIZE_ADDRESS inline void HeapObjectHeader::markWrapperHeader() { | 915 NO_SANITIZE_ADDRESS inline void HeapObjectHeader::markWrapperHeader() { |
| 902 ASSERT(checkHeader()); | 916 ASSERT(checkHeader()); |
| 903 ASSERT(!isWrapperHeaderMarked()); | 917 ASSERT(!isWrapperHeaderMarked()); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 945 return outOfLineAllocate(allocationSize, gcInfoIndex); | 959 return outOfLineAllocate(allocationSize, gcInfoIndex); |
| 946 } | 960 } |
| 947 | 961 |
| 948 inline NormalPageArena* NormalPage::arenaForNormalPage() const { | 962 inline NormalPageArena* NormalPage::arenaForNormalPage() const { |
| 949 return static_cast<NormalPageArena*>(arena()); | 963 return static_cast<NormalPageArena*>(arena()); |
| 950 } | 964 } |
| 951 | 965 |
| 952 } // namespace blink | 966 } // namespace blink |
| 953 | 967 |
| 954 #endif // HeapPage_h | 968 #endif // HeapPage_h |
| OLD | NEW |