[Passwordsafe-devel] SecureAllocator
Popular easy-to-use and secure password manager
Brought to you by:
ronys
From: James C. <Ja...@No...> - 2002-06-21 02:30:59
|
Ok, this mail list has been quiet for a while... Let's see, when we last left off, there was: A) a plan to create a STL allocator, which handled trashMemory as memory was freed, and B) a subtle tweak that I was all talk, no code... SO, here goes... I tried a crack at the SecureAllocator. This is what I came up with: //--------------------------------------------- #include <memory> template <typename T> class SecureAllocator : public std::allocator<T> { // typedef T* pointer; // typedef unsigned int size_type; public: void deallocate(pointer p, size_type n) { trashMemory((unsigned char*)p, n * sizeof(T)); #if defined(_MSC_VER) && _MSC_VER <= 1200 operator delete(p); #else std::allocator<T>::deallocate(p,n); #endif } }; #include <string> typedef std::basic_string<char, std::char_traits<char>, SecureAllocator<char> > SecString; typedef std::basic_string<wchar_t, std::char_traits<wchar_t>, SecureAllocator<wchar_t> > SecWString; //--------------------------------------------- That's it. The #if is needed because VC6 didn't like the fully-qualified call to the base class. VC7 accepted it, as did Comeau C++, although Comeau needed the commented-out typedef's It also appears to work for any other STL collection which takes an allocator: #include <vector> std::vector<int, SecureAllocator<int> > secvector; Note that this works: SecString secstr = "Abcedfg"; cout << secstr << endl; But this does not: string regstr = "Hijkl"; regstr += secstr; string w = secstr + regstr; Seeing that that was so easy, I tried a crack at making it fully generic: As a version which compiled on both VC6 & vc7 required way to many #ifs, I've include separate versions below, and the combined version at the very end. //--------------------------------------------- // Standard C++ version template <typename T> inline void trashMemory2(T* buffer, long length) { trashMemory((unsigned char*) buffer, length); } template <typename T, typename Pr> class beforeDeallocate : public std::allocator<T> { public: // typedef T* pointer; // typedef unsigned int size_type; void deallocate(pointer p, size_type n) { Pr pred; pred(p, n * sizeof(T)); std::allocator<T>::deallocate(p,n); } }; #include <functional> template <class T, class U, class R, R (*F)(T,U)> struct some_binary_function: public std::binary_function<T,U,R> { R operator()(T p, U n) { return F(p, n); } }; template <typename E> class SecureAllocator : public beforeDeallocate<E, some_binary_function<E*, long, VOID, trashMemory2> > { }; //--------------------------------------------- /// VC6 version template <typename T> inline int trashMemory2(T* buffer, long length) { trashMemory((unsigned char*) buffer, length); return 0; } template <typename T, typename Pr> class beforeDeallocate : public std::allocator<T> { public: // typedef T* pointer; // typedef unsigned int size_type; void deallocate(pointer p, size_type n) { Pr pred; pred(p, n * sizeof(T)); operator delete(p); } }; #include <functional> template <class T, class U, class R, R (*F)(T,U)> struct some_binary_function: public std::binary_function<T,U,R> { R operator()(T p, U n) { return F(p, n); } }; template <typename E> class SecureAllocator : public beforeDeallocate<E, some_binary_function<E*, long, int, trashMemory2> > { }; //--------------------------------------------- Most of the differences are because VC6 can't handle a return void. Also, trashMemory2 is needed because some_binary_function requires a function that takes exactly two parameter (with an optional third). Truth, James Curran #if defined(_MSC_VER) && _MSC_VER <= 1200 #define VOID int #else #define VOID void #endif template <typename T> inline VOID trashMemory2(T* buffer, long length) { trashMemory((unsigned char*) buffer, length); #if defined(_MSC_VER) && _MSC_VER <= 1200 return 0; #endif } template <typename T, typename Pr> class beforeDeallocate : public std::allocator<T> { public: // typedef T* pointer; // typedef unsigned int size_type; void deallocate(pointer p, size_type n) { Pr pred; pred(p, n * sizeof(T)); #if defined(_MSC_VER) && _MSC_VER <= 1200 operator delete(p); #else std::allocator<T>::deallocate(p,n); #endif } }; #include <functional> template <class T, class U, class R, R (*F)(T,U)> struct some_binary_function: public std::binary_function<T,U,R> { R operator()(T p, U n) { return F(p, n); } }; template <typename E> class SecureAllocator : public beforeDeallocate<E, some_binary_function<E*, long, VOID, trashMemory2> > { }; |