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

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