1 /* Copyright (C) 2011 Wildfire Games. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining 4 * a copy of this software and associated documentation files (the 5 * "Software"), to deal in the Software without restriction, including 6 * without limitation the rights to use, copy, modify, merge, publish, 7 * distribute, sublicense, and/or sell copies of the Software, and to 8 * permit persons to whom the Software is furnished to do so, subject to 9 * the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included 12 * in all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23 #ifndef INCLUDED_ALLOCATORS_OVERRUN_PROTECTOR 24 #define INCLUDED_ALLOCATORS_OVERRUN_PROTECTOR 25 26 #include "lib/config2.h" // CONFIG2_ALLOCATORS_OVERRUN_PROTECTION 27 #include "lib/sysdep/vm.h" 28 29 /** 30 OverrunProtector wraps an arbitrary object in isolated page(s) and 31 can detect inadvertent writes to it. this is useful for 32 tracking down memory overruns. 33 34 the basic idea is to require users to request access to the object and 35 notify us when done; memory access permission is temporarily granted. 36 (similar in principle to Software Transaction Memory). 37 38 since this is quite slow, the protection is disabled unless 39 CONFIG2_ALLOCATORS_OVERRUN_PROTECTION == 1; this avoids having to remove the 40 wrapper code in release builds and re-write when looking for overruns. 41 42 example usage: 43 OverrunProtector\<T\> wrapper; 44 .. 45 T* p = wrapper.get(); // unlock, make ready for use 46 if(!p) // wrapper's one-time alloc of a T- 47 abort(); // instance had failed - can't continue. 48 DoSomethingWith(p); // (read/write access) 49 wrapper.lock(); // disallow further access until next .get() 50 .. 51 **/ 52 template<class T> class OverrunProtector 53 { 54 NONCOPYABLE(OverrunProtector); // const member 55 public: OverrunProtector()56 OverrunProtector() 57 #if CONFIG2_ALLOCATORS_OVERRUN_PROTECTION 58 : object(new(vm::Allocate(sizeof(T))) T()) 59 #else 60 : object(new T()) 61 #endif 62 { 63 lock(); 64 } 65 ~OverrunProtector()66 ~OverrunProtector() 67 { 68 unlock(); 69 #if CONFIG2_ALLOCATORS_OVERRUN_PROTECTION 70 object->~T(); // call dtor (since we used placement new) 71 vm::Free(object, sizeof(T)); 72 #else 73 delete object; 74 #endif 75 } 76 get()77 T* get() const 78 { 79 unlock(); 80 return object; 81 } 82 lock()83 void lock() const 84 { 85 #if CONFIG2_ALLOCATORS_OVERRUN_PROTECTION 86 vm::Protect(object, sizeof(T), PROT_NONE); 87 #endif 88 } 89 90 private: unlock()91 void unlock() const 92 { 93 #if CONFIG2_ALLOCATORS_OVERRUN_PROTECTION 94 vm::Protect(object, sizeof(T), PROT_READ|PROT_WRITE); 95 #endif 96 } 97 98 T* const object; 99 }; 100 101 #endif // #ifndef INCLUDED_ALLOCATORS_OVERRUN_PROTECTOR 102