diff --git a/src/snmalloc/aal/aal.h b/src/snmalloc/aal/aal.h index 413c284..257e78e 100644 --- a/src/snmalloc/aal/aal.h +++ b/src/snmalloc/aal/aal.h @@ -212,7 +212,8 @@ namespace snmalloc "capptr_bound must preserve non-spatial CapPtr dimensions"); UNUSED(size); - return CapPtr(a.template as_static().unsafe_ptr()); + return CapPtr::unsafe_from( + a.template as_static().unsafe_ptr()); } }; } // namespace snmalloc diff --git a/src/snmalloc/aal/aal_cheri.h b/src/snmalloc/aal/aal_cheri.h index 4774dde..587fdf1 100644 --- a/src/snmalloc/aal/aal_cheri.h +++ b/src/snmalloc/aal/aal_cheri.h @@ -86,7 +86,7 @@ namespace snmalloc } void* pb = __builtin_cheri_bounds_set_exact(a.unsafe_ptr(), size); - return CapPtr(static_cast(pb)); + return CapPtr::unsafe_from(static_cast(pb)); } }; } // namespace snmalloc diff --git a/src/snmalloc/aal/address.h b/src/snmalloc/aal/address.h index 1f528f9..f373918 100644 --- a/src/snmalloc/aal/address.h +++ b/src/snmalloc/aal/address.h @@ -34,7 +34,8 @@ namespace snmalloc inline CapPtr pointer_offset(CapPtr base, size_t diff) { - return CapPtr(pointer_offset(base.unsafe_ptr(), diff)); + return CapPtr::unsafe_from( + pointer_offset(base.unsafe_ptr(), diff)); } /** @@ -51,7 +52,8 @@ namespace snmalloc inline CapPtr pointer_offset_signed(CapPtr base, ptrdiff_t diff) { - return CapPtr(pointer_offset_signed(base.unsafe_ptr(), diff)); + return CapPtr::unsafe_from( + pointer_offset_signed(base.unsafe_ptr(), diff)); } /** @@ -137,7 +139,8 @@ namespace snmalloc SNMALLOC_CONCEPT(capptr::ConceptBound) bounds> inline CapPtr pointer_align_down(CapPtr p) { - return CapPtr(pointer_align_down(p.unsafe_ptr())); + return CapPtr::unsafe_from( + pointer_align_down(p.unsafe_ptr())); } template @@ -174,7 +177,8 @@ namespace snmalloc SNMALLOC_CONCEPT(capptr::ConceptBound) bounds> inline CapPtr pointer_align_up(CapPtr p) { - return CapPtr(pointer_align_up(p.unsafe_ptr())); + return CapPtr::unsafe_from( + pointer_align_up(p.unsafe_ptr())); } template @@ -204,7 +208,8 @@ namespace snmalloc inline CapPtr pointer_align_down(CapPtr p, size_t alignment) { - return CapPtr(pointer_align_down(p.unsafe_ptr(), alignment)); + return CapPtr::unsafe_from( + pointer_align_down(p.unsafe_ptr(), alignment)); } /** @@ -228,7 +233,8 @@ namespace snmalloc inline CapPtr pointer_align_up(CapPtr p, size_t alignment) { - return CapPtr(pointer_align_up(p.unsafe_ptr(), alignment)); + return CapPtr::unsafe_from( + pointer_align_up(p.unsafe_ptr(), alignment)); } /** diff --git a/src/snmalloc/backend/backend.h b/src/snmalloc/backend/backend.h index 5db5841..ae39ca1 100644 --- a/src/snmalloc/backend/backend.h +++ b/src/snmalloc/backend/backend.h @@ -140,12 +140,12 @@ namespace snmalloc Pagemap::set_metaentry(address_cast(alloc), size, t); local_state.get_meta_range().dealloc_range( - capptr::Chunk(&slab_metadata), sizeof(SlabMetadata)); + capptr::Chunk::unsafe_from(&slab_metadata), sizeof(SlabMetadata)); // On non-CHERI platforms, we don't need to re-derive to get a pointer to // the chunk. On CHERI platforms this will need to be stored in the // SlabMetadata or similar. - capptr::Chunk chunk{alloc.unsafe_ptr()}; + auto chunk = capptr::Chunk::unsafe_from(alloc.unsafe_ptr()); local_state.object_range.dealloc_range(chunk, size); } diff --git a/src/snmalloc/backend/fixedglobalconfig.h b/src/snmalloc/backend/fixedglobalconfig.h index a48a55f..9dbfb1e 100644 --- a/src/snmalloc/backend/fixedglobalconfig.h +++ b/src/snmalloc/backend/fixedglobalconfig.h @@ -78,7 +78,7 @@ namespace snmalloc // Push memory into the global range. range_to_pow_2_blocks( - capptr::Chunk(heap_base), + capptr::Chunk::unsafe_from(heap_base), heap_length, [&](capptr::Chunk p, size_t sz, bool) { typename LocalState::GlobalR g; @@ -108,8 +108,8 @@ namespace snmalloc return CapPtr< T, - typename B::template with_wildness>( - p.unsafe_ptr()); + typename B::template with_wildness>:: + unsafe_from(p.unsafe_ptr()); } }; } diff --git a/src/snmalloc/backend_helpers/largebuddyrange.h b/src/snmalloc/backend_helpers/largebuddyrange.h index 379cb5d..59fdf95 100644 --- a/src/snmalloc/backend_helpers/largebuddyrange.h +++ b/src/snmalloc/backend_helpers/largebuddyrange.h @@ -262,8 +262,9 @@ namespace snmalloc { range_to_pow_2_blocks( base, length, [this](capptr::Chunk base, size_t align, bool) { - auto overflow = capptr::Chunk(reinterpret_cast( - buddy_large.add_block(base.unsafe_uintptr(), align))); + auto overflow = + capptr::Chunk::unsafe_from(reinterpret_cast( + buddy_large.add_block(base.unsafe_uintptr(), align))); dealloc_overflow(overflow); }); @@ -358,7 +359,7 @@ namespace snmalloc return nullptr; } - auto result = capptr::Chunk( + auto result = capptr::Chunk::unsafe_from( reinterpret_cast(buddy_large.remove_block(size))); if (result != nullptr) @@ -381,8 +382,9 @@ namespace snmalloc } } - auto overflow = capptr::Chunk(reinterpret_cast( - buddy_large.add_block(base.unsafe_uintptr(), size))); + auto overflow = + capptr::Chunk::unsafe_from(reinterpret_cast( + buddy_large.add_block(base.unsafe_uintptr(), size))); dealloc_overflow(overflow); } }; diff --git a/src/snmalloc/backend_helpers/palrange.h b/src/snmalloc/backend_helpers/palrange.h index efa324e..e2094f9 100644 --- a/src/snmalloc/backend_helpers/palrange.h +++ b/src/snmalloc/backend_helpers/palrange.h @@ -28,8 +28,8 @@ namespace snmalloc if constexpr (pal_supports) { SNMALLOC_ASSERT(size >= PAL::minimum_alloc_size); - auto result = - capptr::Chunk(PAL::template reserve_aligned(size)); + auto result = capptr::Chunk::unsafe_from( + PAL::template reserve_aligned(size)); #ifdef SNMALLOC_TRACING message<1024>("Pal range alloc: {} ({})", result.unsafe_ptr(), size); @@ -38,7 +38,7 @@ namespace snmalloc } else { - auto result = capptr::Chunk(PAL::reserve(size)); + auto result = capptr::Chunk::unsafe_from(PAL::reserve(size)); #ifdef SNMALLOC_TRACING message<1024>("Pal range alloc: {} ({})", result.unsafe_ptr(), size); diff --git a/src/snmalloc/backend_helpers/smallbuddyrange.h b/src/snmalloc/backend_helpers/smallbuddyrange.h index 8e7de03..53e82ba 100644 --- a/src/snmalloc/backend_helpers/smallbuddyrange.h +++ b/src/snmalloc/backend_helpers/smallbuddyrange.h @@ -33,7 +33,7 @@ namespace snmalloc { SNMALLOC_ASSERT((address_cast(r) & MASK) == 0); if (r == nullptr) - *ptr = capptr::Chunk( + *ptr = capptr::Chunk::unsafe_from( reinterpret_cast((*ptr).unsafe_uintptr() & MASK)); else // Preserve lower bit. @@ -71,7 +71,8 @@ namespace snmalloc if (new_is_red) { if (old_addr == nullptr) - *r = capptr::Chunk(reinterpret_cast(MASK)); + *r = capptr::Chunk::unsafe_from( + reinterpret_cast(MASK)); else *r = pointer_offset(old_addr, MASK).template as_static(); } diff --git a/src/snmalloc/ds_core/ptrwrap.h b/src/snmalloc/ds_core/ptrwrap.h index 2543855..f602800 100644 --- a/src/snmalloc/ds_core/ptrwrap.h +++ b/src/snmalloc/ds_core/ptrwrap.h @@ -283,6 +283,7 @@ namespace snmalloc constexpr SNMALLOC_FAST_PATH CapPtr() : CapPtr(nullptr) {} + private: /** * all other constructions must be explicit * @@ -302,13 +303,25 @@ namespace snmalloc # pragma warning(pop) #endif + public: + /** + * The CapPtr constructor is not sufficiently intimidating, given that it + * can be used to break annotation correctness. Expose it with a better + * name. + */ + static constexpr SNMALLOC_FAST_PATH CapPtr unsafe_from(T* p) + { + return CapPtr(p); + } + /** * Allow static_cast<>-s that preserve bounds but vary the target type. */ template [[nodiscard]] SNMALLOC_FAST_PATH CapPtr as_static() const { - return CapPtr(static_cast(this->unsafe_capptr)); + return CapPtr::unsafe_from( + static_cast(this->unsafe_capptr)); } [[nodiscard]] SNMALLOC_FAST_PATH CapPtr as_void() const @@ -322,7 +335,8 @@ namespace snmalloc template [[nodiscard]] SNMALLOC_FAST_PATH CapPtr as_reinterpret() const { - return CapPtr(reinterpret_cast(this->unsafe_capptr)); + return CapPtr::unsafe_from( + reinterpret_cast(this->unsafe_capptr)); } SNMALLOC_FAST_PATH bool operator==(const CapPtr& rhs) const @@ -396,7 +410,7 @@ namespace snmalloc inline SNMALLOC_FAST_PATH capptr::Alloc capptr_chunk_is_alloc(capptr::ChunkUser p) { - return capptr::Alloc(p.unsafe_ptr()); + return capptr::Alloc::unsafe_from(p.unsafe_ptr()); } /** @@ -426,7 +440,7 @@ namespace snmalloc static inline SNMALLOC_FAST_PATH capptr::AllocWild capptr_from_client(void* p) { - return capptr::AllocWild(p); + return capptr::AllocWild::unsafe_from(p); } /** @@ -440,8 +454,8 @@ namespace snmalloc { return CapPtr< T, - typename B::template with_wildness>( - p.unsafe_ptr()); + typename B::template with_wildness>:: + unsafe_from(p.unsafe_ptr()); } /** @@ -490,7 +504,7 @@ namespace snmalloc SNMALLOC_FAST_PATH CapPtr load(std::memory_order order = std::memory_order_seq_cst) noexcept { - return CapPtr(this->unsafe_capptr.load(order)); + return CapPtr::unsafe_from(this->unsafe_capptr.load(order)); } SNMALLOC_FAST_PATH void store( @@ -504,7 +518,7 @@ namespace snmalloc CapPtr desired, std::memory_order order = std::memory_order_seq_cst) noexcept { - return CapPtr( + return CapPtr::unsafe_from( this->unsafe_capptr.exchange(desired.unsafe_ptr(), order)); } diff --git a/src/snmalloc/mem/backend_wrappers.h b/src/snmalloc/mem/backend_wrappers.h index 605b505..2d8b7ee 100644 --- a/src/snmalloc/mem/backend_wrappers.h +++ b/src/snmalloc/mem/backend_wrappers.h @@ -102,8 +102,8 @@ namespace snmalloc UNUSED(ls); return CapPtr< T, - typename B::template with_wildness>( - p.unsafe_ptr()); + typename B::template with_wildness>:: + unsafe_from(p.unsafe_ptr()); } } } // namespace snmalloc diff --git a/src/snmalloc/mem/corealloc.h b/src/snmalloc/mem/corealloc.h index 98cf0b7..aa6adc5 100644 --- a/src/snmalloc/mem/corealloc.h +++ b/src/snmalloc/mem/corealloc.h @@ -506,10 +506,10 @@ namespace snmalloc * The front of the queue has already been validated; just change the * annotating type. */ - auto domesticate_first = [](freelist::QueuePtr p) - SNMALLOC_FAST_PATH_LAMBDA { - return freelist::HeadPtr(p.unsafe_ptr()); - }; + auto domesticate_first = + [](freelist::QueuePtr p) SNMALLOC_FAST_PATH_LAMBDA { + return freelist::HeadPtr::unsafe_from(p.unsafe_ptr()); + }; message_queue().dequeue(key_global, domesticate_first, domesticate, cb); } else diff --git a/src/snmalloc/mem/freelist.h b/src/snmalloc/mem/freelist.h index 3c70307..7d67750 100644 --- a/src/snmalloc/mem/freelist.h +++ b/src/snmalloc/mem/freelist.h @@ -270,7 +270,8 @@ namespace snmalloc inline static BQueuePtr encode_next( address_t curr, BHeadPtr next, const FreeListKey& key) { - return BQueuePtr(code_next(curr, next.unsafe_ptr(), key)); + return BQueuePtr::unsafe_from( + code_next(curr, next.unsafe_ptr(), key)); } /** @@ -294,7 +295,8 @@ namespace snmalloc inline static BHeadPtr decode_next( address_t curr, BHeadPtr next, const FreeListKey& key) { - return BHeadPtr(code_next(curr, next.unsafe_ptr(), key)); + return BHeadPtr::unsafe_from( + code_next(curr, next.unsafe_ptr(), key)); } template< @@ -543,7 +545,7 @@ namespace snmalloc Object::BHeadPtr cast_head(uint32_t ix) { - return Object::BHeadPtr( + return Object::BHeadPtr::unsafe_from( static_cast*>(head[ix])); } @@ -715,8 +717,8 @@ namespace snmalloc // this is doing a CONTAINING_RECORD like cast to get back // to the actual object. This isn't true if the builder is // empty, but you are not allowed to call this in the empty case. - auto last = - Object::BHeadPtr(Object::from_next_ptr(cast_end(0))); + auto last = Object::BHeadPtr::unsafe_from( + Object::from_next_ptr(cast_end(0))); init(); return {first, last}; } diff --git a/src/snmalloc/mem/remotecache.h b/src/snmalloc/mem/remotecache.h index 50e4c9b..a415a1d 100644 --- a/src/snmalloc/mem/remotecache.h +++ b/src/snmalloc/mem/remotecache.h @@ -115,7 +115,7 @@ namespace snmalloc if constexpr (Config::Options.QueueHeadsAreTame) { auto domesticate_nop = [](freelist::QueuePtr p) { - return freelist::HeadPtr(p.unsafe_ptr()); + return freelist::HeadPtr::unsafe_from(p.unsafe_ptr()); }; remote->enqueue(first, last, key, domesticate_nop); } diff --git a/src/snmalloc/pal/pal.h b/src/snmalloc/pal/pal.h index 31b846d..a425085 100644 --- a/src/snmalloc/pal/pal.h +++ b/src/snmalloc/pal/pal.h @@ -90,7 +90,8 @@ namespace snmalloc CapPtr>> capptr_to_user_address_control(CapPtr p) { - return CapPtr>(p.unsafe_ptr()); + return CapPtr>::unsafe_from( + p.unsafe_ptr()); } template< diff --git a/src/snmalloc/pal/pal_freebsd.h b/src/snmalloc/pal/pal_freebsd.h index d24f4b7..4c5c028 100644 --- a/src/snmalloc/pal/pal_freebsd.h +++ b/src/snmalloc/pal/pal_freebsd.h @@ -135,7 +135,7 @@ namespace snmalloc return nullptr; } } - return CapPtr>( + return CapPtr>::unsafe_from( __builtin_cheri_perms_and( p.unsafe_ptr(), ~static_cast(CHERI_PERM_SW_VMEM))); } diff --git a/src/test/func/domestication/domestication.cc b/src/test/func/domestication/domestication.cc index 123a441..c0ae603 100644 --- a/src/test/func/domestication/domestication.cc +++ b/src/test/func/domestication/domestication.cc @@ -108,8 +108,8 @@ namespace snmalloc return CapPtr< T, - typename B::template with_wildness>( - p.unsafe_ptr()); + typename B::template with_wildness>:: + unsafe_from(p.unsafe_ptr()); } };