diff --git a/dll.cpp b/dll.cpp index a51a897e..9efaec78 100644 --- a/dll.cpp +++ b/dll.cpp @@ -56,18 +56,9 @@ static PDelete s_pDelete = NULL; static void * CRYPTOPP_CDECL New (size_t size) { - new_handler newHandler = set_new_handler(NULL); - if (newHandler) - set_new_handler(newHandler); - void *p; while (!(p = malloc(size))) - { - if (newHandler) - newHandler(); - else - throw std::bad_alloc(); - } + CallNewHandler(); return p; } diff --git a/integer.cpp b/integer.cpp index 258007ab..5cb3a8d8 100644 --- a/integer.cpp +++ b/integer.cpp @@ -46,16 +46,23 @@ static const char s_RunAtStartup = (AssignIntToInteger = FunctionAssignIntToInte template CPP_TYPENAME AllocatorBase::pointer AlignedAllocator::allocate(size_type n, const void *) { + CheckSize(n); + if (n == 0) + return NULL; #ifdef SSE2_INTRINSICS_AVAILABLE if (n >= 4) - #ifdef __GNUC__ - return (T *)memalign(16, sizeof(T)*n); - #else - return (T *)_mm_malloc(sizeof(T)*n, 16); - #endif - else + { + void *p; + #ifdef __GNUC__ + while (!(p = memalign(16, sizeof(T)*n))) + #else + while (!(p = _mm_malloc(sizeof(T)*n, 16))) + #endif + CallNewHandler(); + return (T*)p; + } #endif - return new T[n]; + return new T[n]; } template diff --git a/misc.cpp b/misc.cpp index 27a9a354..825b4466 100644 --- a/misc.cpp +++ b/misc.cpp @@ -6,6 +6,7 @@ #include "misc.h" #include "words.h" +#include NAMESPACE_BEGIN(CryptoPP) @@ -75,6 +76,22 @@ unsigned long Crop(unsigned long value, unsigned int size) return value; } +#if !(defined(_MSC_VER) && (_MSC_VER < 1300)) +using std::new_handler; +#endif + +void CallNewHandler() +{ + new_handler newHandler = set_new_handler(NULL); + if (newHandler) + set_new_handler(newHandler); + + if (newHandler) + newHandler(); + else + throw std::bad_alloc(); +} + NAMESPACE_END #endif diff --git a/misc.h b/misc.h index 659ba2a7..d73d210f 100644 --- a/misc.h +++ b/misc.h @@ -59,6 +59,58 @@ private: void operator=(const NotCopyable &); }; +template +struct NewObject +{ + T* operator()() const {return new T;} +}; + +// This function safely initializes a static object in a multithreaded environment without using locks. +// It may leak memory when two threads try to initialize the static object at the same time +// but this should be acceptable since each static object is only initialized once per session. +template , int instance=0> +class Singleton +{ +public: + Singleton(F objectFactory = F()) : m_objectFactory(objectFactory) {} + + // VC60 workaround: use "..." to prevent this function from being inlined + const T & Ref(...) const; + +private: + F m_objectFactory; +}; + +template +const T & Singleton::Ref(...) const +{ + static simple_ptr s_pObject; + static char s_objectState = 0; + +retry: + switch (s_objectState) + { + case 0: + s_objectState = 1; + try + { + s_pObject.m_p = m_objectFactory(); + } + catch(...) + { + s_objectState = 0; + throw; + } + s_objectState = 2; + break; + case 1: + goto retry; + default: + break; + } + return *s_pObject.m_p; +} + // ************** misc functions *************** // can't use std::min or std::max in MSVC60 or Cygwin 1.1.0 @@ -209,57 +261,7 @@ inline CipherDir GetCipherDir(const T &obj) return obj.IsForwardTransformation() ? ENCRYPTION : DECRYPTION; } -template -struct NewObject -{ - T* operator()() const {return new T;} -}; - -// This function safely initializes a static object in a multithreaded environment without using locks. -// It may leak memory when two threads try to initialize the static object at the same time -// but this should be acceptable since each static object is only initialized once per session. -template , int instance=0> -class Singleton -{ -public: - Singleton(F objectFactory = F()) : m_objectFactory(objectFactory) {} - - // VC60 workaround: use "..." to prevent this function from being inlined - const T & Ref(...) const; - -private: - F m_objectFactory; -}; - -template -const T & Singleton::Ref(...) const -{ - static simple_ptr s_pObject; - static char s_objectState = 0; - -retry: - switch (s_objectState) - { - case 0: - s_objectState = 1; - try - { - s_pObject.m_p = m_objectFactory(); - } - catch(...) - { - s_objectState = 0; - throw; - } - s_objectState = 2; - break; - case 1: - goto retry; - default: - break; - } - return *s_pObject.m_p; -} +void CallNewHandler(); // ************** rotate functions *************** diff --git a/secblock.h b/secblock.h index d763bc5b..821f5f79 100644 --- a/secblock.h +++ b/secblock.h @@ -32,7 +32,14 @@ public: const_pointer address(const_reference r) const {return (&r); } void construct(pointer p, const T& val) {new (p) T(val);} void destroy(pointer p) {p->~T();} - size_type max_size() const {return size_type(-1)/sizeof(T);} + size_type max_size() const {return ~size_type(0)/sizeof(T);} // switch to std::numeric_limits::max later + +protected: + static void CheckSize(size_t n) + { + if (n > ~size_t(0) / sizeof(T)) + throw InvalidArgument("AllocatorBase: requested size would cause integer overflow"); + } }; #define CRYPTOPP_INHERIT_ALLOCATOR_TYPES \ @@ -72,10 +79,10 @@ public: pointer allocate(size_type n, const void * = NULL) { - if (n > 0) - return new T[n]; - else + CheckSize(n); + if (n == 0) return NULL; + return new T[n]; } void deallocate(void *p, size_type n)