From 2d3901ae5d79df26cf0afab4b11f487368da637b Mon Sep 17 00:00:00 2001 From: Fredrik Roubert Date: Thu, 15 Nov 2018 14:01:42 +0100 Subject: [PATCH] ICU-20271 Use C++11 operator new = delete to disallow heap allocation. --- icu4c/source/common/cmemory.h | 37 ++++++++-------------- icu4c/source/common/unicode/localpointer.h | 13 ++++---- icu4c/source/common/uresimp.h | 14 ++++---- icu4c/source/i18n/fphdlimp.h | 7 ++-- 4 files changed, 33 insertions(+), 38 deletions(-) diff --git a/icu4c/source/common/cmemory.h b/icu4c/source/common/cmemory.h index c9a20f22e15..a570d535bea 100644 --- a/icu4c/source/common/cmemory.h +++ b/icu4c/source/common/cmemory.h @@ -290,6 +290,13 @@ inline T *LocalMemory::allocateInsteadAndCopy(int32_t newCapacity, int32_t le template class MaybeStackArray { public: + // No heap allocation. Use only on the stack. + static void* U_EXPORT2 operator new(size_t) U_NO_THROW = delete; + static void* U_EXPORT2 operator new[](size_t) U_NO_THROW = delete; +#if U_HAVE_PLACEMENT_NEW + static void* U_EXPORT2 operator new(size_t, void*) U_NO_THROW = delete; +#endif + /** * Default constructor initializes with internal T[stackCapacity] buffer. */ @@ -402,20 +409,6 @@ private: /* No ownership transfer: No copy constructor, no assignment operator. */ MaybeStackArray(const MaybeStackArray & /*other*/) {} void operator=(const MaybeStackArray & /*other*/) {} - - // No heap allocation. Use only on the stack. - // (Declaring these functions private triggers a cascade of problems: - // MSVC insists on exporting an instantiation of MaybeStackArray, which - // requires that all functions be defined. - // An empty implementation of new() is rejected, it must return a value. - // Returning NULL is rejected by gcc for operator new. - // The expedient thing is just not to override operator new. - // While relatively pointless, heap allocated instances will function. - // static void * U_EXPORT2 operator new(size_t size); - // static void * U_EXPORT2 operator new[](size_t size); -#if U_HAVE_PLACEMENT_NEW - // static void * U_EXPORT2 operator new(size_t, void *ptr); -#endif }; template @@ -512,6 +505,13 @@ inline T *MaybeStackArray::orphanOrClone(int32_t length, int32 template class MaybeStackHeaderAndArray { public: + // No heap allocation. Use only on the stack. + static void* U_EXPORT2 operator new(size_t) U_NO_THROW = delete; + static void* U_EXPORT2 operator new[](size_t) U_NO_THROW = delete; +#if U_HAVE_PLACEMENT_NEW + static void* U_EXPORT2 operator new(size_t, void*) U_NO_THROW = delete; +#endif + /** * Default constructor initializes with internal H+T[stackCapacity] buffer. */ @@ -608,15 +608,6 @@ private: /* No ownership transfer: No copy constructor, no assignment operator. */ MaybeStackHeaderAndArray(const MaybeStackHeaderAndArray & /*other*/) {} void operator=(const MaybeStackHeaderAndArray & /*other*/) {} - - // No heap allocation. Use only on the stack. - // (Declaring these functions private triggers a cascade of problems; - // see the MaybeStackArray class for details.) - // static void * U_EXPORT2 operator new(size_t size); - // static void * U_EXPORT2 operator new[](size_t size); -#if U_HAVE_PLACEMENT_NEW - // static void * U_EXPORT2 operator new(size_t, void *ptr); -#endif }; template diff --git a/icu4c/source/common/unicode/localpointer.h b/icu4c/source/common/unicode/localpointer.h index e17ee3d886e..9ed874b706a 100644 --- a/icu4c/source/common/unicode/localpointer.h +++ b/icu4c/source/common/unicode/localpointer.h @@ -65,6 +65,13 @@ U_NAMESPACE_BEGIN template class LocalPointerBase { public: + // No heap allocation. Use only on the stack. + static void* U_EXPORT2 operator new(size_t) = delete; + static void* U_EXPORT2 operator new[](size_t) = delete; +#if U_HAVE_PLACEMENT_NEW + static void* U_EXPORT2 operator new(size_t, void*) = delete; +#endif + /** * Constructor takes ownership. * @param p simple pointer to an object that is adopted @@ -158,12 +165,6 @@ private: // No ownership sharing: No copy constructor, no assignment operator. LocalPointerBase(const LocalPointerBase &other); void operator=(const LocalPointerBase &other); - // No heap allocation. Use only on the stack. - static void * U_EXPORT2 operator new(size_t size); - static void * U_EXPORT2 operator new[](size_t size); -#if U_HAVE_PLACEMENT_NEW - static void * U_EXPORT2 operator new(size_t, void *ptr); -#endif }; /** diff --git a/icu4c/source/common/uresimp.h b/icu4c/source/common/uresimp.h index 6aa8b36dd93..4a2a369c5c7 100644 --- a/icu4c/source/common/uresimp.h +++ b/icu4c/source/common/uresimp.h @@ -108,6 +108,13 @@ U_NAMESPACE_BEGIN */ class StackUResourceBundle { public: + // No heap allocation. Use only on the stack. + static void* U_EXPORT2 operator new(size_t) U_NO_THROW = delete; + static void* U_EXPORT2 operator new[](size_t) U_NO_THROW = delete; +#if U_HAVE_PLACEMENT_NEW + static void* U_EXPORT2 operator new(size_t, void*) U_NO_THROW = delete; +#endif + StackUResourceBundle(); ~StackUResourceBundle(); @@ -121,13 +128,6 @@ public: private: UResourceBundle bundle; - - // No heap allocation. Use only on the stack. - static void* U_EXPORT2 operator new(size_t); - static void* U_EXPORT2 operator new[](size_t); -#if U_HAVE_PLACEMENT_NEW - static void* U_EXPORT2 operator new(size_t, void*); -#endif }; U_NAMESPACE_END diff --git a/icu4c/source/i18n/fphdlimp.h b/icu4c/source/i18n/fphdlimp.h index a6827e01e98..797682f93a9 100644 --- a/icu4c/source/i18n/fphdlimp.h +++ b/icu4c/source/i18n/fphdlimp.h @@ -62,8 +62,11 @@ class FieldPositionIteratorHandler : public FieldPositionHandler { // to be destroyed before status goes out of scope. Easiest thing is to // allocate us on the stack in the same (or narrower) scope as status has. // This attempts to encourage that by blocking heap allocation. - void *operator new(size_t s); - void *operator new[](size_t s); + static void* U_EXPORT2 operator new(size_t) U_NO_THROW = delete; + static void* U_EXPORT2 operator new[](size_t) U_NO_THROW = delete; +#if U_HAVE_PLACEMENT_NEW + static void* U_EXPORT2 operator new(size_t, void*) U_NO_THROW = delete; +#endif public: FieldPositionIteratorHandler(FieldPositionIterator* posIter, UErrorCode& status);