]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_utilities/lib/alloc.h
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / libsecurity_utilities / lib / alloc.h
index 83403e01cfb04d5fdd2d24e3ce55a4652153b218..b77f945157cdd08d029ab837eef1930be85d8a59 100644 (file)
@@ -43,44 +43,62 @@ namespace Security
 class Allocator {
 public:
        virtual ~Allocator();
-       virtual void *malloc(size_t) throw(std::bad_alloc) = 0;
-       virtual void free(void *) throw() = 0;
-       virtual void *realloc(void *, size_t) throw(std::bad_alloc) = 0;
+       virtual void *malloc(size_t)= 0;
+       virtual void free(void *) _NOEXCEPT = 0;
+       virtual void *realloc(void *, size_t)= 0;
 
        //
        // Template versions for added expressiveness.
        // Note that the integers are element counts, not byte sizes.
        //
-       template <class T> T *alloc() throw(std::bad_alloc)
+       template <class T> T *alloc()
        { return reinterpret_cast<T *>(malloc(sizeof(T))); }
 
-       template <class T> T *alloc(UInt32 count) throw(std::bad_alloc)
-       { return reinterpret_cast<T *>(malloc(sizeof(T) * count)); }
+       template <class T> T *alloc(UInt32 count)
+       {
+        size_t bytes = 0;
+        if (__builtin_mul_overflow(sizeof(T), count, &bytes)) {
+            throw std::bad_alloc();
+        }
+        return reinterpret_cast<T *>(malloc(bytes));
+
+    }
 
-       template <class T> T *alloc(T *old, UInt32 count) throw(std::bad_alloc)
-       { return reinterpret_cast<T *>(realloc(old, sizeof(T) * count)); }
+       template <class T> T *alloc(T *old, UInt32 count)
+       {
+        size_t bytes = 0;
+        if (__builtin_mul_overflow(sizeof(T), count, &bytes)) {
+            throw std::bad_alloc();
+        }
+        return reinterpret_cast<T *>(realloc(old, bytes));
+    }
        
         
        //
        // Happier malloc/realloc for any type. Note that these still have
        // the original (byte-sized) argument profile.
        //
-       template <class T> T *malloc(size_t size) throw(std::bad_alloc)
+       template <class T> T *malloc(size_t size)
        { return reinterpret_cast<T *>(malloc(size)); }
        
-       template <class T> T *realloc(void *addr, size_t size) throw(std::bad_alloc)
+       template <class T> T *realloc(void *addr, size_t size)
        { return reinterpret_cast<T *>(realloc(addr, size)); }
 
        // All right, if you *really* have to have calloc...
-       void *calloc(size_t size, size_t count) throw(std::bad_alloc)
+       void *calloc(size_t size, size_t count)
        {
-               void *addr = malloc(size * count);
-               memset(addr, 0, size * count);
+        size_t bytes = 0;
+        if(__builtin_mul_overflow(size, count, &bytes)) {
+            // Multiplication overflowed.
+            throw std::bad_alloc();
+        }
+               void *addr = malloc(bytes);
+               memset(addr, 0, bytes);
                return addr;
        }
        
        // compare Allocators for identity
-       virtual bool operator == (const Allocator &alloc) const throw();
+       virtual bool operator == (const Allocator &alloc) const _NOEXCEPT;
 
 public:
        // allocator chooser options
@@ -99,14 +117,14 @@ public:
 // Use this to cleanly destroy things.
 //
 template <class T>
-inline void destroy(T *obj, Allocator &alloc) throw()
+inline void destroy(T *obj, Allocator &alloc) _NOEXCEPT
 {
        obj->~T();
        alloc.free(obj);
 }
 
 // untyped (release memory only, no destructor call)
-inline void destroy(void *obj, Allocator &alloc) throw()
+inline void destroy(void *obj, Allocator &alloc) _NOEXCEPT
 {
        alloc.free(obj);
 }
@@ -127,17 +145,17 @@ inline void destroy(void *obj, Allocator &alloc) throw()
 //
 class CssmHeap {
 public:    
-       void *operator new (size_t size, Allocator *alloc = NULL) throw(std::bad_alloc);
-       void operator delete (void *addr, size_t size) throw();
-       void operator delete (void *addr, size_t size, Allocator *alloc) throw();
+       void *operator new (size_t size, Allocator *alloc = NULL);
+       void operator delete (void *addr, size_t size) _NOEXCEPT;
+       void operator delete (void *addr, size_t size, Allocator *alloc) _NOEXCEPT;
 };
 
 
 //
-// Here is a version of auto_ptr that works with Allocators. It is designed
+// Here is a version of unique_ptr that works with Allocators. It is designed
 // to be pretty much a drop-in replacement. It requires an allocator as a constructor
 // argument, of course.
-// Note that CssmAutoPtr<void> is perfectly valid, unlike its auto_ptr look-alike.
+// Note that CssmAutoPtr<void> is perfectly valid, unlike its unique_ptr look-alike.
 // You can't dereference it, naturally.
 //
 template <class T>
@@ -158,7 +176,7 @@ public:
        
        ~CssmAutoPtr()                          { allocator.free(mine); }
        
-       T *get() const throw()          { return mine; }
+       T *get() const _NOEXCEPT                { return mine; }
        T *release()                            { T *result = mine; mine = NULL; return result; }
        void reset()                            { allocator.free(mine); mine = NULL; }
 
@@ -185,7 +203,7 @@ public:
        
        ~CssmAutoPtr()                          { destroy(mine, allocator); }
        
-       void *get() throw()             { return mine; }
+       void *get() _NOEXCEPT           { return mine; }
        void *release()                         { void *result = mine; mine = NULL; return result; }
        void reset()                            { allocator.free(mine); mine = NULL; }
 
@@ -230,10 +248,10 @@ public:
 //
 // Global C++ allocation hooks to use Allocators (global namespace)
 //
-inline void *operator new (size_t size, Allocator &allocator) throw (std::bad_alloc)
+inline void *operator new (size_t size, Allocator &allocator)
 { return allocator.malloc(size); }
 
-inline void *operator new[] (size_t size, Allocator &allocator) throw (std::bad_alloc)
+inline void *operator new[] (size_t size, Allocator &allocator)
 { return allocator.malloc(size); }