Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(329)

Side by Side Diff: third_party/WebKit/Source/platform/heap/HeapPage.h

Issue 2723743003: Use the Oilpan heap canary only on 64-bit. (Closed)
Patch Set: Hide the implementation of |getMagic|, too, unless 64-bit. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | third_party/WebKit/Source/platform/heap/HeapPage.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/Source/platform/heap/HeapPage.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698