From d56201e28d2b502faa0f57762afc93bb59302a55 Mon Sep 17 00:00:00 2001 From: David Chisnall Date: Tue, 13 Aug 2019 15:01:30 +0100 Subject: [PATCH] Add type confusion protection to the default memory provider. --- src/ds/helpers.h | 19 +++++++++++++++++++ src/mem/alloc.h | 13 +++---------- src/mem/globalalloc.h | 2 +- src/mem/largealloc.h | 5 ++++- src/mem/pagemap.h | 2 +- src/mem/threadalloc.h | 2 +- 6 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/ds/helpers.h b/src/ds/helpers.h index 7fe6633..a30af27 100644 --- a/src/ds/helpers.h +++ b/src/ds/helpers.h @@ -42,6 +42,25 @@ namespace snmalloc } }; + /** + * A singleton global. Used to allow globals in headers. Precisely one + * instance of the static field will exist in the final program, irrespective + * of the number of compilation units that reference the field. + * + * C++ globals do not have their types as part of the name mangling, so this + * allows a singleton instance of a specific type that won't be confused with + * other template instantiations of the same type. + */ + template + struct TypedSingleton + { + /** + * The global variable, which will have a mangled name that includes the + * type of `T`. + */ + static inline T global; + }; + /** * Wrapper for wrapping values. * diff --git a/src/mem/alloc.h b/src/mem/alloc.h index 61128e0..ce2ff40 100644 --- a/src/mem/alloc.h +++ b/src/mem/alloc.h @@ -60,7 +60,7 @@ namespace snmalloc * variable. This should be used from within the library or program that * owns the pagemap. * - * This class makes the global pagemap a static field so that its name + * This class makes the global pagemap a typed singleton so that its name * includes the type mangling. If two compilation units try to instantiate * two different types of pagemap then they will see two distinct pagemaps. * This will prevent allocating with one and freeing with the other (because @@ -69,21 +69,14 @@ namespace snmalloc * having two different types. */ template - class GlobalPagemapTemplate + struct GlobalPagemapTemplate { - /** - * The global pagemap variable. The name of this symbol will include the - * type of `T`. - */ - inline static T global_pagemap; - - public: /** * Returns the pagemap. */ static SuperslabPagemap& pagemap() { - return global_pagemap; + return TypedSingleton::global; } }; diff --git a/src/mem/globalalloc.h b/src/mem/globalalloc.h index 591a70b..92ade2c 100644 --- a/src/mem/globalalloc.h +++ b/src/mem/globalalloc.h @@ -38,7 +38,7 @@ namespace snmalloc static AllocPool* make() noexcept { - return make(default_memory_provider); + return AllocPool::make(default_memory_provider()); } Alloc* acquire() diff --git a/src/mem/largealloc.h b/src/mem/largealloc.h index 08048b9..2dcf7c3 100644 --- a/src/mem/largealloc.h +++ b/src/mem/largealloc.h @@ -405,5 +405,8 @@ namespace snmalloc * The memory provider that will be used if no other provider is explicitly * passed as an argument. */ - inline GlobalVirtual default_memory_provider; + inline GlobalVirtual& default_memory_provider() + { + return TypedSingleton::global; + } } // namespace snmalloc diff --git a/src/mem/pagemap.h b/src/mem/pagemap.h index b8ef6fd..ae4f164 100644 --- a/src/mem/pagemap.h +++ b/src/mem/pagemap.h @@ -145,7 +145,7 @@ namespace snmalloc if (e->compare_exchange_strong( value, LOCKED_ENTRY, std::memory_order_relaxed)) { - auto& v = default_memory_provider; + auto& v = default_memory_provider(); value = v.alloc_chunk(); e->store(value, std::memory_order_release); } diff --git a/src/mem/threadalloc.h b/src/mem/threadalloc.h index b5b24d3..dab3c1b 100644 --- a/src/mem/threadalloc.h +++ b/src/mem/threadalloc.h @@ -19,7 +19,7 @@ namespace snmalloc * required. This avoids a branch on the fast path. */ inline Alloc GlobalPlaceHolder( - default_memory_provider, SNMALLOC_DEFAULT_PAGEMAP(), nullptr, true); + default_memory_provider(), SNMALLOC_DEFAULT_PAGEMAP(), nullptr, true); #ifdef SNMALLOC_EXTERNAL_THREAD_ALLOC /**