diff options
author | Moonchild <moonchild@palemoon.org> | 2020-08-03 09:41:42 +0000 |
---|---|---|
committer | Moonchild <moonchild@palemoon.org> | 2020-08-06 18:31:58 +0000 |
commit | e1e535c1c6372f95b4a14b6a00b6d6e7be400c3b (patch) | |
tree | 1e0cda7c9382d4f3fa8da42eb3ea5cf219572b0f /js | |
parent | 9b6252893876995ae4c1f278fc8d1cbdfb72e94d (diff) | |
download | uxp-e1e535c1c6372f95b4a14b6a00b6d6e7be400c3b.tar.gz |
[js] Try to catch bad pointers for GC and bail if not valid.
Diffstat (limited to 'js')
-rw-r--r-- | js/public/HeapAPI.h | 37 | ||||
-rw-r--r-- | js/src/gc/Marking.cpp | 5 |
2 files changed, 42 insertions, 0 deletions
diff --git a/js/public/HeapAPI.h b/js/public/HeapAPI.h index fef6c0c780..d033d3706e 100644 --- a/js/public/HeapAPI.h +++ b/js/public/HeapAPI.h @@ -51,6 +51,7 @@ const size_t ChunkMarkBitmapBits = 129024; const size_t ChunkRuntimeOffset = ChunkSize - sizeof(void*); const size_t ChunkTrailerSize = 2 * sizeof(uintptr_t) + sizeof(uint64_t); const size_t ChunkLocationOffset = ChunkSize - ChunkTrailerSize; +const size_t ChunkStoreBufferOffset = ChunkSize - ChunkTrailerSize + sizeof(uint64_t); const size_t ArenaZoneOffset = sizeof(size_t); const size_t ArenaHeaderSize = sizeof(size_t) + 2 * sizeof(uintptr_t) + sizeof(size_t) + sizeof(uintptr_t); @@ -326,6 +327,20 @@ CellIsMarkedGray(const Cell* cell) extern JS_PUBLIC_API(bool) CellIsMarkedGrayIfKnown(const Cell* cell); +MOZ_ALWAYS_INLINE ChunkLocation GetCellLocation(const void* cell) { + uintptr_t addr = uintptr_t(cell); + addr &= ~js::gc::ChunkMask; + addr |= js::gc::ChunkLocationOffset; + return *reinterpret_cast<ChunkLocation*>(addr); +} + +MOZ_ALWAYS_INLINE bool NurseryCellHasStoreBuffer(const void* cell) { + uintptr_t addr = uintptr_t(cell); + addr &= ~js::gc::ChunkMask; + addr |= js::gc::ChunkStoreBufferOffset; + return *reinterpret_cast<void**>(addr) != nullptr; +} + } /* namespace detail */ MOZ_ALWAYS_INLINE bool @@ -341,6 +356,28 @@ IsInsideNursery(const js::gc::Cell* cell) return location == ChunkLocation::Nursery; } +MOZ_ALWAYS_INLINE bool IsCellPointerValid(const void* cell) { + auto addr = uintptr_t(cell); + if (addr < ChunkSize || addr % CellSize != 0) { + return false; + } + auto location = detail::GetCellLocation(cell); + if (location == ChunkLocation::TenuredHeap) { + return !!detail::GetGCThingZone(addr); + } + if (location == ChunkLocation::Nursery) { + return detail::NurseryCellHasStoreBuffer(cell); + } + return false; +} + +MOZ_ALWAYS_INLINE bool IsCellPointerValidOrNull(const void* cell) { + if (!cell) { + return true; + } + return IsCellPointerValid(cell); +} + } /* namespace gc */ } /* namespace js */ diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp index 43e325394d..b4db0297a6 100644 --- a/js/src/gc/Marking.cpp +++ b/js/src/gc/Marking.cpp @@ -2267,6 +2267,8 @@ void js::gc::StoreBuffer::SlotsEdge::trace(TenuringTracer& mover) const { NativeObject* obj = object(); + if(!IsCellPointerValid(obj)) + return; // Beware JSObject::swap exchanging a native object for a non-native one. if (!obj->isNative()) @@ -2336,6 +2338,8 @@ js::gc::StoreBuffer::traceWholeCells(TenuringTracer& mover) { for (ArenaCellSet* cells = bufferWholeCell; cells; cells = cells->next) { Arena* arena = cells->arena; + if(!IsCellPointerValid(arena)) + continue; MOZ_ASSERT(arena->bufferedCells == cells); arena->bufferedCells = &ArenaCellSet::Empty; @@ -2364,6 +2368,7 @@ js::gc::StoreBuffer::CellPtrEdge::trace(TenuringTracer& mover) const { if (!*edge) return; + // XXX: We should check if the cell pointer is valid here too MOZ_ASSERT((*edge)->getTraceKind() == JS::TraceKind::Object); mover.traverse(reinterpret_cast<JSObject**>(edge)); |