Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: mojo/system/memory.h

Issue 418033005: Mojo: Change how we handle invalid pointer arguments (at the system layer). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: review changes Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « mojo/system/mapping_table.cc ('k') | mojo/system/memory.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef MOJO_SYSTEM_MEMORY_H_ 5 #ifndef MOJO_SYSTEM_MEMORY_H_
6 #define MOJO_SYSTEM_MEMORY_H_ 6 #define MOJO_SYSTEM_MEMORY_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h>
10 #include <string.h> // For |memcpy()|.
9 11
12 #include "base/macros.h"
13 #include "base/memory/scoped_ptr.h"
10 #include "mojo/public/c/system/macros.h" 14 #include "mojo/public/c/system/macros.h"
11 #include "mojo/system/system_impl_export.h" 15 #include "mojo/system/system_impl_export.h"
12 16
13 namespace mojo { 17 namespace mojo {
14 namespace system { 18 namespace system {
15 19
16 namespace internal { 20 namespace internal {
17 21
22 // Removes |const| from |T| (available as |remove_const<T>::type|):
23 // TODO(vtl): Remove these once we have the C++11 |remove_const|.
24 template <typename T> struct remove_const { typedef T type; };
25 template <typename T> struct remove_const<const T> { typedef T type; };
26
27 // Yields |(const) char| if |T| is |(const) void|, else |T|:
28 template <typename T> struct VoidToChar { typedef T type; };
29 template <> struct VoidToChar<void> { typedef char type; };
30 template <> struct VoidToChar<const void> { typedef const char type; };
31
32 template <size_t size, size_t alignment>
33 void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerHelper(const void* pointer);
34
35 template <size_t size, size_t alignment>
36 void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerWithCountHelper(
37 const void* pointer,
38 size_t count);
39
40 // TODO(vtl): Delete all the |Verify...()| things (and replace them with
41 // |Check...()|.
18 template <size_t size, size_t alignment> 42 template <size_t size, size_t alignment>
19 bool MOJO_SYSTEM_IMPL_EXPORT VerifyUserPointerHelper(const void* pointer); 43 bool MOJO_SYSTEM_IMPL_EXPORT VerifyUserPointerHelper(const void* pointer);
20 44
21 // Note: This is also used by options_validation.h. 45 // Note: This is also used by options_validation.h.
22 template <size_t size, size_t alignment> 46 template <size_t size, size_t alignment>
23 bool MOJO_SYSTEM_IMPL_EXPORT VerifyUserPointerWithCountHelper( 47 bool MOJO_SYSTEM_IMPL_EXPORT VerifyUserPointerWithCountHelper(
24 const void* pointer, 48 const void* pointer,
25 size_t count); 49 size_t count);
26 50
27 } // namespace internal 51 } // namespace internal
28 52
53 // Forward declarations so that they can be friended.
54 template <typename Type> class UserPointerReader;
55 template <typename Type> class UserPointerWriter;
56 template <typename Type> class UserPointerReaderWriter;
57
29 // Verify (insofar as possible/necessary) that a |T| can be read from the user 58 // Verify (insofar as possible/necessary) that a |T| can be read from the user
30 // |pointer|. 59 // |pointer|.
31 template <typename T> 60 template <typename T>
32 bool VerifyUserPointer(const T* pointer) { 61 bool VerifyUserPointer(const T* pointer) {
33 return internal::VerifyUserPointerHelper<sizeof(T), MOJO_ALIGNOF(T)>(pointer); 62 return internal::VerifyUserPointerHelper<sizeof(T), MOJO_ALIGNOF(T)>(pointer);
34 } 63 }
35 64
36 // Verify (insofar as possible/necessary) that |count| |T|s can be read from the 65 // Verify (insofar as possible/necessary) that |count| |T|s can be read from the
37 // user |pointer|; |count| may be zero. (This is done carefully since |count * 66 // user |pointer|; |count| may be zero. (This is done carefully since |count *
38 // sizeof(T)| may overflow a |size_t|.) 67 // sizeof(T)| may overflow a |size_t|.)
39 template <typename T> 68 template <typename T>
40 bool VerifyUserPointerWithCount(const T* pointer, size_t count) { 69 bool VerifyUserPointerWithCount(const T* pointer, size_t count) {
41 return internal::VerifyUserPointerWithCountHelper<sizeof(T), 70 return internal::VerifyUserPointerWithCountHelper<sizeof(T),
42 MOJO_ALIGNOF(T)>(pointer, 71 MOJO_ALIGNOF(T)>(pointer,
43 count); 72 count);
44 } 73 }
45 74
46 // Verify that |size| bytes (which may be zero) can be read from the user 75 // Verify that |size| bytes (which may be zero) can be read from the user
47 // |pointer|, and that |pointer| has the specified |alignment| (if |size| is 76 // |pointer|, and that |pointer| has the specified |alignment| (if |size| is
48 // nonzero). 77 // nonzero).
49 template <size_t alignment> 78 template <size_t alignment>
50 bool MOJO_SYSTEM_IMPL_EXPORT VerifyUserPointerWithSize(const void* pointer, 79 bool MOJO_SYSTEM_IMPL_EXPORT VerifyUserPointerWithSize(const void* pointer,
51 size_t size); 80 size_t size);
52 81
82 // Provides a convenient way to implicitly get null |UserPointer<Type>|s.
83 struct NullUserPointer {};
84
85 // Represents a user pointer to a single |Type| (which must be POD), for Mojo
86 // primitive parameters.
87 //
88 // Use a const |Type| for in parameters, and non-const |Type|s for out and
89 // in-out parameters (in which case the |Put()| method is available).
90 template <typename Type>
91 class UserPointer {
92 public:
93 // Instead of explicitly using these constructors, you can often use
94 // |MakeUserPointer()| (or |NullUserPointer()| for null pointers). (The common
95 // exception is when you have, e.g., a |char*| and want to get a
96 // |UserPointer<void>|.)
97 UserPointer() : pointer_(NULL) {}
98 explicit UserPointer(Type* pointer) : pointer_(pointer) {}
99 // Allow implicit conversion from the "null user pointer".
100 UserPointer(NullUserPointer) : pointer_(NULL) {}
101 ~UserPointer() {}
102
103 // Allow assignment from the "null user pointer".
104 UserPointer<Type>& operator=(NullUserPointer) {
105 pointer_ = NULL;
106 return *this;
107 }
108
109 // Allow conversion to a "non-const" |UserPointer|.
110 operator UserPointer<const Type>() const {
111 return UserPointer<const Type>(pointer_);
112 }
113
114 bool IsNull() const {
115 return !pointer_;
116 }
117
118 // We want to force a copy here, so return |Type| not |const Type&|.
119 Type Get() const {
120 internal::CheckUserPointerHelper<sizeof(Type),
121 MOJO_ALIGNOF(Type)>(pointer_);
122 return *pointer_;
123 }
124
125 // Note: This |Put()| method is not valid when |T| is const, e.g., |const
126 // uint32_t|, but it's okay to include them so long as this template is only
127 // implicitly instantiated (see 14.7.1 of the C++11 standard) and not
128 // explicitly instantiated. (On implicit instantiation, only the declarations
129 // need be valid, not the definitions.)
130 //
131 // If |Type| is |void|, we "convert" it to |char|, so that it makes sense.
132 // (Otherwise, we'd need a suitable specialization to exclude |Put()|.)
133 //
134 // In C++11, we could do something like:
135 // template <typename _Type = Type>
136 // typename enable_if<!is_const<_Type>::value &&
137 // !is_void<_Type>::value>::type Put(
138 // const _Type& value) { ... }
139 // (which obviously be correct), but C++03 doesn't allow default function
140 // template arguments.
141 void Put(const typename internal::VoidToChar<Type>::type& value) {
142 internal::CheckUserPointerHelper<sizeof(Type),
143 MOJO_ALIGNOF(Type)>(pointer_);
144 *pointer_ = value;
145 }
146
147 UserPointer At(size_t i) const {
148 return UserPointer(pointer_ + i);
149 }
150
151 // TODO(vtl): This is temporary. Get rid of this. (We should pass
152 // |UserPointer<>|s along appropriately, or access data in a safe way
153 // everywhere.)
154 Type* GetPointerUnsafe() const {
155 return pointer_;
156 }
157
158 // These provides safe (read-only/write-only/read-and-write) access to a
159 // |UserPointer<Type>| (probably pointing to an array) using just an ordinary
160 // pointer (obtained via |GetPointer()|).
161 //
162 // The memory returned by |GetPointer()| may be a copy of the original user
163 // memory, but should be modified only if the user is intended to eventually
164 // see the change.) If any changes are made, |Commit()| should be called to
165 // guarantee that the changes are written back to user memory (it may be
166 // called multiple times).
167 //
168 // Note: These classes are designed to allow fast, unsafe implementations (in
169 // which |GetPointer()| just returns the user pointer) if desired. Thus if
170 // |Commit()| is *not* called, changes may or may not be made visible to the
171 // user.
172 //
173 // Use these classes in the following way:
174 //
175 // MojoResult Core::PutFoos(UserPointer<const uint32_t> foos,
176 // uint32_t num_foos) {
177 // UserPointer<const uint32_t>::Reader foos_reader(foos, num_foos);
178 // return PutFoosImpl(foos_reader.GetPointer(), num_foos);
179 // }
180 //
181 // MojoResult Core::GetFoos(UserPointer<uint32_t> foos,
182 // uint32_t num_foos) {
183 // UserPointer<uint32_t>::Writer foos_writer(foos, num_foos);
184 // MojoResult rv = GetFoosImpl(foos.GetPointer(), num_foos);
185 // foos_writer.Commit();
186 // return rv;
187 // }
188 //
189 // TODO(vtl): Possibly, since we're not really being safe, we should just not
190 // copy for Release builds.
191 typedef UserPointerReader<Type> Reader;
192 typedef UserPointerWriter<Type> Writer;
193 typedef UserPointerReaderWriter<Type> ReaderWriter;
194
195 private:
196 friend class UserPointerReader<Type>;
197 friend class UserPointerWriter<Type>;
198 friend class UserPointerReaderWriter<Type>;
199
200 Type* pointer_;
201 // Allow copy and assignment.
202 };
203
204 // Provides a convenient way to make a |UserPointer<Type>|.
205 template <typename Type>
206 inline UserPointer<Type> MakeUserPointer(Type* pointer) {
207 return UserPointer<Type>(pointer);
208 }
209
210 // Implementation of |UserPointer<Type>::Reader|.
211 template <typename Type>
212 class UserPointerReader {
213 private:
214 typedef typename internal::remove_const<Type>::type TypeNoConst;
215
216 public:
217 UserPointerReader(UserPointer<const Type> user_pointer, size_t count) {
218 Init(user_pointer.pointer_, count);
219 }
220 UserPointerReader(UserPointer<TypeNoConst> user_pointer, size_t count) {
221 Init(user_pointer.pointer_, count);
222 }
223
224 const Type* GetPointer() const { return buffer_.get(); }
225
226 private:
227 void Init(const Type* user_pointer, size_t count) {
228 internal::CheckUserPointerWithCountHelper<
229 sizeof(Type), MOJO_ALIGNOF(Type)>(user_pointer, count);
230 buffer_.reset(new TypeNoConst[count]);
231 memcpy(buffer_.get(), user_pointer, count * sizeof(Type));
232 }
233
234 scoped_ptr<TypeNoConst[]> buffer_;
235
236 DISALLOW_COPY_AND_ASSIGN(UserPointerReader);
237 };
238
239 // Implementation of |UserPointer<Type>::Writer|.
240 template <typename Type>
241 class UserPointerWriter {
242 public:
243 UserPointerWriter(UserPointer<Type> user_pointer, size_t count)
244 : user_pointer_(user_pointer),
245 count_(count) {
246 buffer_.reset(new Type[count_]);
247 memset(buffer_.get(), 0, count_ * sizeof(Type));
248 }
249
250 Type* GetPointer() const { return buffer_.get(); }
251
252 void Commit() {
253 internal::CheckUserPointerWithCountHelper<
254 sizeof(Type), MOJO_ALIGNOF(Type)>(user_pointer_.pointer_, count_);
255 memcpy(user_pointer_.pointer_, buffer_.get(), count_ * sizeof(Type));
256 }
257
258 private:
259 UserPointer<Type> user_pointer_;
260 size_t count_;
261 scoped_ptr<Type[]> buffer_;
262
263 DISALLOW_COPY_AND_ASSIGN(UserPointerWriter);
264 };
265
266 // Implementation of |UserPointer<Type>::ReaderWriter|.
267 template <typename Type>
268 class UserPointerReaderWriter {
269 public:
270 UserPointerReaderWriter(UserPointer<Type> user_pointer, size_t count)
271 : user_pointer_(user_pointer),
272 count_(count) {
273 internal::CheckUserPointerWithCountHelper<
274 sizeof(Type), MOJO_ALIGNOF(Type)>(user_pointer_.pointer_, count_);
275 buffer_.reset(new Type[count]);
276 memcpy(buffer_.get(), user_pointer.pointer_, count * sizeof(Type));
277 }
278
279 Type* GetPointer() const { return buffer_.get(); }
280 size_t GetCount() const { return count_; }
281
282 void Commit() {
283 internal::CheckUserPointerWithCountHelper<
284 sizeof(Type), MOJO_ALIGNOF(Type)>(user_pointer_.pointer_, count_);
285 memcpy(user_pointer_.pointer_, buffer_.get(), count_ * sizeof(Type));
286 }
287
288 private:
289 UserPointer<Type> user_pointer_;
290 size_t count_;
291 scoped_ptr<Type[]> buffer_;
292
293 DISALLOW_COPY_AND_ASSIGN(UserPointerReaderWriter);
294 };
295
296 // Represents a user pointer that will never be dereferenced by the system. The
297 // pointer value (i.e., the address) may be as a key for lookup, or may be a
298 // value that is only passed to the user at some point.
299 template <typename Type>
300 class UserPointerValue {
301 public:
302 UserPointerValue() : pointer_() {}
303 explicit UserPointerValue(Type* pointer) : pointer_(pointer) {}
304 ~UserPointerValue() {}
305
306 // Returns the *value* of the pointer, which shouldn't be cast back to a
307 // pointer and dereferenced.
308 uintptr_t GetValue() const {
309 return reinterpret_cast<uintptr_t>(pointer_);
310 }
311
312 private:
313 Type* pointer_;
314 // Allow copy and assignment.
315 };
316
317 // Provides a convenient way to make a |UserPointerValue<Type>|.
318 template <typename Type>
319 inline UserPointerValue<Type> MakeUserPointerValue(Type* pointer) {
320 return UserPointerValue<Type>(pointer);
321 }
322
53 } // namespace system 323 } // namespace system
54 } // namespace mojo 324 } // namespace mojo
55 325
56 #endif // MOJO_SYSTEM_MEMORY_H_ 326 #endif // MOJO_SYSTEM_MEMORY_H_
OLDNEW
« no previous file with comments | « mojo/system/mapping_table.cc ('k') | mojo/system/memory.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698