From 2ba0de76b3bde3888875188fbb76398f614e95aa Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Tue, 20 Jul 2021 12:13:56 +0100 Subject: [PATCH] mem/metaslab: use uintptr_t alignment functions It is UB to offset from `nullptr` (except perhaps with a 0 offset). Apparently clang is able to use this to reason, given `void* p`, that comparing `__builtin_align_down(p, x)` against `handle.fake_large_remote` (i.e., a `static inline constexpr` `nullptr`) must be the same as comparing `p` itself against `nullptr`. In `MetaEntry`'s constructor, converting the provided `RemoteAllocator*` to `uintptr_t` before offsetting avoids the UB. (While here, don't use `address_cast()`, as `address_t` will, on CHERI, be `ptraddr_t` and not `uintptr_t`.) Doing the alignment in `get_remote` at `uintptr_t` before casting to `RemoteAllocator*`, rather than converting and then aligning, prevents the reasoning above from eliminating the alignment. --- src/mem/metaslab.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mem/metaslab.h b/src/mem/metaslab.h index 9d774e2..ae2b7ea 100644 --- a/src/mem/metaslab.h +++ b/src/mem/metaslab.h @@ -180,8 +180,9 @@ namespace snmalloc MetaEntry(Metaslab* meta, RemoteAllocator* remote, sizeclass_t sizeclass) : meta(meta) { + /* remote might be nullptr; cast to uintptr_t before offsetting */ remote_and_sizeclass = - address_cast(pointer_offset(remote, sizeclass)); + pointer_offset(reinterpret_cast(remote), sizeclass); } [[nodiscard]] Metaslab* get_metaslab() const @@ -192,7 +193,7 @@ namespace snmalloc [[nodiscard]] RemoteAllocator* get_remote() const { return reinterpret_cast( - bits::align_down(remote_and_sizeclass, alignof(RemoteAllocator))); + pointer_align_down(remote_and_sizeclass)); } [[nodiscard]] sizeclass_t get_sizeclass() const