Line data Source code
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:
56 1 : OverrunProtector()
57 : #if CONFIG2_ALLOCATORS_OVERRUN_PROTECTION
58 : : object(new(vm::Allocate(sizeof(T))) T())
59 : #else
60 1 : : object(new T())
61 : #endif
62 : {
63 1 : lock();
64 1 : }
65 :
66 1 : ~OverrunProtector()
67 : {
68 1 : 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 1 : delete object;
74 : #endif
75 1 : }
76 :
77 0 : T* get() const
78 : {
79 0 : unlock();
80 0 : return object;
81 : }
82 :
83 0 : void lock() const
84 : {
85 : #if CONFIG2_ALLOCATORS_OVERRUN_PROTECTION
86 : vm::Protect(object, sizeof(T), PROT_NONE);
87 : #endif
88 0 : }
89 :
90 : private:
91 0 : void unlock() const
92 : {
93 : #if CONFIG2_ALLOCATORS_OVERRUN_PROTECTION
94 : vm::Protect(object, sizeof(T), PROT_READ|PROT_WRITE);
95 : #endif
96 0 : }
97 :
98 : T* const object;
99 : };
100 :
101 : #endif // #ifndef INCLUDED_ALLOCATORS_OVERRUN_PROTECTOR
|