Apply patch for [CVE-2012-2677][boost] ordered_malloc() overflow
[external/boost.git] / boost / python / extract.hpp
1 // Copyright David Abrahams 2002.
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5 #ifndef EXTRACT_DWA200265_HPP
6 # define EXTRACT_DWA200265_HPP
7
8 # include <boost/python/detail/prefix.hpp>
9
10 # include <boost/python/converter/object_manager.hpp>
11 # include <boost/python/converter/from_python.hpp>
12 # include <boost/python/converter/rvalue_from_python_data.hpp>
13 # include <boost/python/converter/registered.hpp>
14 # include <boost/python/converter/registered_pointee.hpp>
15
16 # include <boost/python/object_core.hpp>
17 # include <boost/python/refcount.hpp>
18
19 # include <boost/python/detail/copy_ctor_mutates_rhs.hpp>
20 # include <boost/python/detail/void_ptr.hpp>
21 # include <boost/python/detail/void_return.hpp>
22 # include <boost/utility.hpp>
23 # include <boost/call_traits.hpp>
24
25 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) || BOOST_WORKAROUND(BOOST_INTEL_WIN, <= 900)
26 // workaround for VC++ 6.x or 7.0
27 # define BOOST_EXTRACT_WORKAROUND ()
28 #else
29 # define BOOST_EXTRACT_WORKAROUND
30 #endif
31
32 namespace boost { namespace python {
33
34 namespace api
35 {
36   class object;
37 }
38
39 namespace converter
40 {
41   template <class Ptr>
42   struct extract_pointer
43   {
44       typedef Ptr result_type;
45       extract_pointer(PyObject*);
46       
47       bool check() const;
48       Ptr operator()() const;
49       
50    private:
51       PyObject* m_source;
52       void* m_result;
53   };
54   
55   template <class Ref>
56   struct extract_reference
57   {
58       typedef Ref result_type;
59       extract_reference(PyObject*);
60       
61       bool check() const;
62       Ref operator()() const;
63       
64    private:
65       PyObject* m_source;
66       void* m_result;
67   };
68   
69   template <class T>
70   struct extract_rvalue : private noncopyable
71   {
72       typedef typename mpl::if_<
73           python::detail::copy_ctor_mutates_rhs<T>
74         , T&
75         , typename call_traits<T>::param_type
76       >::type result_type;
77
78       extract_rvalue(PyObject*);
79
80       bool check() const;
81       result_type operator()() const;
82    private:
83       PyObject* m_source;
84       mutable rvalue_from_python_data<T> m_data;
85   };
86   
87   template <class T>
88   struct extract_object_manager
89   {
90       typedef T result_type;
91       extract_object_manager(PyObject*);
92
93       bool check() const;
94       result_type operator()() const;
95    private:
96       PyObject* m_source;
97   };
98   
99   template <class T>
100   struct select_extract
101   {
102       BOOST_STATIC_CONSTANT(
103           bool, obj_mgr = is_object_manager<T>::value);
104
105       BOOST_STATIC_CONSTANT(
106           bool, ptr = is_pointer<T>::value);
107     
108       BOOST_STATIC_CONSTANT(
109           bool, ref = is_reference<T>::value);
110
111       typedef typename mpl::if_c<
112           obj_mgr
113           , extract_object_manager<T>
114           , typename mpl::if_c<
115               ptr
116               , extract_pointer<T>
117               , typename mpl::if_c<
118                   ref
119                   , extract_reference<T>
120                   , extract_rvalue<T>
121                 >::type
122             >::type
123          >::type type;
124   };
125 }
126
127 template <class T>
128 struct extract
129     : converter::select_extract<T>::type
130 {
131  private:
132     typedef typename converter::select_extract<T>::type base;
133  public:
134     typedef typename base::result_type result_type;
135     
136     operator result_type() const
137     {
138         return (*this)();
139     }
140     
141     extract(PyObject*);
142     extract(api::object const&);
143 };
144
145 //
146 // Implementations
147 //
148 template <class T>
149 inline extract<T>::extract(PyObject* o)
150     : base(o)
151 {
152 }
153
154 template <class T>
155 inline extract<T>::extract(api::object const& o)
156     : base(o.ptr())
157 {
158 }
159
160 namespace converter
161 {
162   template <class T>
163   inline extract_rvalue<T>::extract_rvalue(PyObject* x)
164       : m_source(x)
165       , m_data(
166           (rvalue_from_python_stage1)(x, registered<T>::converters)
167           )
168   {
169   }
170   
171   template <class T>
172   inline bool
173   extract_rvalue<T>::check() const
174   {
175       return m_data.stage1.convertible;
176   }
177
178   template <class T>
179   inline typename extract_rvalue<T>::result_type
180   extract_rvalue<T>::operator()() const
181   {
182       return *(T*)(
183           // Only do the stage2 conversion once
184           m_data.stage1.convertible ==  m_data.storage.bytes
185              ? m_data.storage.bytes
186              : (rvalue_from_python_stage2)(m_source, m_data.stage1, registered<T>::converters)
187           );
188   }
189
190   template <class Ref>
191   inline extract_reference<Ref>::extract_reference(PyObject* obj)
192       : m_source(obj)
193       , m_result(
194           (get_lvalue_from_python)(obj, registered<Ref>::converters)
195           )
196   {
197   }
198
199   template <class Ref>
200   inline bool extract_reference<Ref>::check() const
201   {
202       return m_result != 0;
203   }
204
205   template <class Ref>
206   inline Ref extract_reference<Ref>::operator()() const
207   {
208       if (m_result == 0)
209           (throw_no_reference_from_python)(m_source, registered<Ref>::converters);
210       
211       return python::detail::void_ptr_to_reference(m_result, (Ref(*)())0);
212   }
213
214   template <class Ptr>
215   inline extract_pointer<Ptr>::extract_pointer(PyObject* obj)
216       : m_source(obj)
217       , m_result(
218           obj == Py_None ? 0 : (get_lvalue_from_python)(obj, registered_pointee<Ptr>::converters)
219           )
220   {
221   }
222
223   template <class Ptr>
224   inline bool extract_pointer<Ptr>::check() const
225   {
226       return m_source == Py_None || m_result != 0;
227   }
228
229   template <class Ptr>
230   inline Ptr extract_pointer<Ptr>::operator()() const
231   {
232       if (m_result == 0 && m_source != Py_None)
233           (throw_no_pointer_from_python)(m_source, registered_pointee<Ptr>::converters);
234       
235       return Ptr(m_result);
236   }
237
238   template <class T>
239   inline extract_object_manager<T>::extract_object_manager(PyObject* obj)
240       : m_source(obj)
241   {
242   }
243
244   template <class T>
245   inline bool extract_object_manager<T>::check() const
246   {
247       return object_manager_traits<T>::check(m_source);
248   }
249
250   template <class T>
251   inline T extract_object_manager<T>::operator()() const
252   {
253       return T(
254           object_manager_traits<T>::adopt(python::incref(m_source))
255           );
256   }
257 }
258   
259 }} // namespace boost::python::converter
260
261 #endif // EXTRACT_DWA200265_HPP