OLD | NEW |
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_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ | 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ |
6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ | 6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ |
7 | 7 |
8 #include <new> | 8 #include <new> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
| 11 #include "mojo/public/c/system/macros.h" |
11 #include "mojo/public/cpp/bindings/lib/bindings_internal.h" | 12 #include "mojo/public/cpp/bindings/lib/bindings_internal.h" |
12 #include "mojo/public/cpp/bindings/lib/bindings_serialization.h" | 13 #include "mojo/public/cpp/bindings/lib/bindings_serialization.h" |
13 #include "mojo/public/cpp/bindings/lib/bounds_checker.h" | 14 #include "mojo/public/cpp/bindings/lib/bounds_checker.h" |
14 #include "mojo/public/cpp/bindings/lib/buffer.h" | 15 #include "mojo/public/cpp/bindings/lib/buffer.h" |
| 16 #include "mojo/public/cpp/bindings/lib/template_util.h" |
15 #include "mojo/public/cpp/bindings/lib/validation_errors.h" | 17 #include "mojo/public/cpp/bindings/lib/validation_errors.h" |
16 #include "mojo/public/cpp/environment/logging.h" | 18 #include "mojo/public/cpp/environment/logging.h" |
17 | 19 |
18 namespace mojo { | 20 namespace mojo { |
19 template <typename T> class Array; | 21 template <typename T> class Array; |
20 class String; | 22 class String; |
21 | 23 |
22 namespace internal { | 24 namespace internal { |
23 | 25 |
24 template <typename T> | 26 template <typename T> |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 return ((num_elements + 7) / 8); | 105 return ((num_elements + 7) / 8); |
104 } | 106 } |
105 static BitRef ToRef(StorageType* storage, size_t offset) { | 107 static BitRef ToRef(StorageType* storage, size_t offset) { |
106 return BitRef(&storage[offset / 8], 1 << (offset % 8)); | 108 return BitRef(&storage[offset / 8], 1 << (offset % 8)); |
107 } | 109 } |
108 static bool ToConstRef(const StorageType* storage, size_t offset) { | 110 static bool ToConstRef(const StorageType* storage, size_t offset) { |
109 return (storage[offset / 8] & (1 << (offset % 8))) != 0; | 111 return (storage[offset / 8] & (1 << (offset % 8))) != 0; |
110 } | 112 } |
111 }; | 113 }; |
112 | 114 |
| 115 // Array type information needed for valdiation. |
| 116 template <uint32_t in_expected_num_elements, |
| 117 bool in_element_nullable, |
| 118 typename InElementValidateParams> |
| 119 class ArrayValidateParams { |
| 120 public: |
| 121 // Validation information for elements. It is either another specialization of |
| 122 // ArrayValidateParams (if elements are arrays) or NoValidateParams. |
| 123 typedef InElementValidateParams ElementValidateParams; |
| 124 |
| 125 // If |expected_num_elements| is not 0, the array is expected to have exactly |
| 126 // that number of elements. |
| 127 static const uint32_t expected_num_elements = in_expected_num_elements; |
| 128 // Whether the elements are nullable. |
| 129 static const bool element_nullable = in_element_nullable; |
| 130 }; |
| 131 |
| 132 // NoValidateParams is used to indicate the end of an ArrayValidateParams chain. |
| 133 class NoValidateParams { |
| 134 }; |
| 135 |
113 // What follows is code to support the serialization of Array_Data<T>. There | 136 // What follows is code to support the serialization of Array_Data<T>. There |
114 // are two interesting cases: arrays of primitives and arrays of objects. | 137 // are two interesting cases: arrays of primitives and arrays of objects. |
115 // Arrays of objects are represented as arrays of pointers to objects. | 138 // Arrays of objects are represented as arrays of pointers to objects. |
116 | 139 |
117 template <typename T, bool kIsHandle> struct ArraySerializationHelper; | 140 template <typename T, bool is_handle> struct ArraySerializationHelper; |
118 | 141 |
119 template <typename T> | 142 template <typename T> |
120 struct ArraySerializationHelper<T, false> { | 143 struct ArraySerializationHelper<T, false> { |
121 typedef typename ArrayDataTraits<T>::StorageType ElementType; | 144 typedef typename ArrayDataTraits<T>::StorageType ElementType; |
122 | 145 |
123 static void EncodePointersAndHandles(const ArrayHeader* header, | 146 static void EncodePointersAndHandles(const ArrayHeader* header, |
124 ElementType* elements, | 147 ElementType* elements, |
125 std::vector<Handle>* handles) { | 148 std::vector<Handle>* handles) { |
126 } | 149 } |
127 | 150 |
128 static void DecodePointersAndHandles(const ArrayHeader* header, | 151 static void DecodePointersAndHandles(const ArrayHeader* header, |
129 ElementType* elements, | 152 ElementType* elements, |
130 std::vector<Handle>* handles) { | 153 std::vector<Handle>* handles) { |
131 } | 154 } |
132 | 155 |
| 156 template <bool element_nullable, typename ElementValidateParams> |
133 static bool ValidateElements(const ArrayHeader* header, | 157 static bool ValidateElements(const ArrayHeader* header, |
134 const ElementType* elements, | 158 const ElementType* elements, |
135 BoundsChecker* bounds_checker) { | 159 BoundsChecker* bounds_checker) { |
| 160 MOJO_COMPILE_ASSERT(!element_nullable, |
| 161 Primitive_type_should_be_non_nullable); |
| 162 MOJO_COMPILE_ASSERT( |
| 163 (IsSame<ElementValidateParams, NoValidateParams>::value), |
| 164 Primitive_type_should_not_have_array_validate_params); |
136 return true; | 165 return true; |
137 } | 166 } |
138 }; | 167 }; |
139 | 168 |
140 template <> | 169 template <> |
141 struct ArraySerializationHelper<Handle, true> { | 170 struct ArraySerializationHelper<Handle, true> { |
142 typedef ArrayDataTraits<Handle>::StorageType ElementType; | 171 typedef ArrayDataTraits<Handle>::StorageType ElementType; |
143 | 172 |
144 static void EncodePointersAndHandles(const ArrayHeader* header, | 173 static void EncodePointersAndHandles(const ArrayHeader* header, |
145 ElementType* elements, | 174 ElementType* elements, |
146 std::vector<Handle>* handles); | 175 std::vector<Handle>* handles); |
147 | 176 |
148 static void DecodePointersAndHandles(const ArrayHeader* header, | 177 static void DecodePointersAndHandles(const ArrayHeader* header, |
149 ElementType* elements, | 178 ElementType* elements, |
150 std::vector<Handle>* handles); | 179 std::vector<Handle>* handles); |
151 | 180 |
| 181 template <bool element_nullable, typename ElementValidateParams> |
152 static bool ValidateElements(const ArrayHeader* header, | 182 static bool ValidateElements(const ArrayHeader* header, |
153 const ElementType* elements, | 183 const ElementType* elements, |
154 BoundsChecker* bounds_checker); | 184 BoundsChecker* bounds_checker) { |
| 185 MOJO_COMPILE_ASSERT( |
| 186 (IsSame<ElementValidateParams, NoValidateParams>::value), |
| 187 Handle_type_should_not_have_array_validate_params); |
| 188 |
| 189 for (uint32_t i = 0; i < header->num_elements; ++i) { |
| 190 if (IsNonNullableValidationEnabled() && !element_nullable && |
| 191 elements[i].value() == kEncodedInvalidHandleValue) { |
| 192 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE); |
| 193 return false; |
| 194 } |
| 195 if (!bounds_checker->ClaimHandle(elements[i])) { |
| 196 ReportValidationError(VALIDATION_ERROR_ILLEGAL_HANDLE); |
| 197 return false; |
| 198 } |
| 199 } |
| 200 return true; |
| 201 } |
155 }; | 202 }; |
156 | 203 |
157 template <typename H> | 204 template <typename H> |
158 struct ArraySerializationHelper<H, true> { | 205 struct ArraySerializationHelper<H, true> { |
159 typedef typename ArrayDataTraits<H>::StorageType ElementType; | 206 typedef typename ArrayDataTraits<H>::StorageType ElementType; |
160 | 207 |
161 static void EncodePointersAndHandles(const ArrayHeader* header, | 208 static void EncodePointersAndHandles(const ArrayHeader* header, |
162 ElementType* elements, | 209 ElementType* elements, |
163 std::vector<Handle>* handles) { | 210 std::vector<Handle>* handles) { |
164 ArraySerializationHelper<Handle, true>::EncodePointersAndHandles( | 211 ArraySerializationHelper<Handle, true>::EncodePointersAndHandles( |
165 header, elements, handles); | 212 header, elements, handles); |
166 } | 213 } |
167 | 214 |
168 static void DecodePointersAndHandles(const ArrayHeader* header, | 215 static void DecodePointersAndHandles(const ArrayHeader* header, |
169 ElementType* elements, | 216 ElementType* elements, |
170 std::vector<Handle>* handles) { | 217 std::vector<Handle>* handles) { |
171 ArraySerializationHelper<Handle, true>::DecodePointersAndHandles( | 218 ArraySerializationHelper<Handle, true>::DecodePointersAndHandles( |
172 header, elements, handles); | 219 header, elements, handles); |
173 } | 220 } |
174 | 221 |
| 222 template <bool element_nullable, typename ElementValidateParams> |
175 static bool ValidateElements(const ArrayHeader* header, | 223 static bool ValidateElements(const ArrayHeader* header, |
176 const ElementType* elements, | 224 const ElementType* elements, |
177 BoundsChecker* bounds_checker) { | 225 BoundsChecker* bounds_checker) { |
178 return ArraySerializationHelper<Handle, true>::ValidateElements( | 226 return ArraySerializationHelper<Handle, true>:: |
179 header, elements, bounds_checker); | 227 ValidateElements<element_nullable, ElementValidateParams>( |
| 228 header, elements, bounds_checker); |
180 } | 229 } |
181 }; | 230 }; |
182 | 231 |
183 template <typename P> | 232 template <typename P> |
184 struct ArraySerializationHelper<P*, false> { | 233 struct ArraySerializationHelper<P*, false> { |
185 typedef typename ArrayDataTraits<P*>::StorageType ElementType; | 234 typedef typename ArrayDataTraits<P*>::StorageType ElementType; |
186 | 235 |
187 static void EncodePointersAndHandles(const ArrayHeader* header, | 236 static void EncodePointersAndHandles(const ArrayHeader* header, |
188 ElementType* elements, | 237 ElementType* elements, |
189 std::vector<Handle>* handles) { | 238 std::vector<Handle>* handles) { |
190 for (uint32_t i = 0; i < header->num_elements; ++i) | 239 for (uint32_t i = 0; i < header->num_elements; ++i) |
191 Encode(&elements[i], handles); | 240 Encode(&elements[i], handles); |
192 } | 241 } |
193 | 242 |
194 static void DecodePointersAndHandles(const ArrayHeader* header, | 243 static void DecodePointersAndHandles(const ArrayHeader* header, |
195 ElementType* elements, | 244 ElementType* elements, |
196 std::vector<Handle>* handles) { | 245 std::vector<Handle>* handles) { |
197 for (uint32_t i = 0; i < header->num_elements; ++i) | 246 for (uint32_t i = 0; i < header->num_elements; ++i) |
198 Decode(&elements[i], handles); | 247 Decode(&elements[i], handles); |
199 } | 248 } |
200 | 249 |
| 250 template <bool element_nullable, typename ElementValidateParams> |
201 static bool ValidateElements(const ArrayHeader* header, | 251 static bool ValidateElements(const ArrayHeader* header, |
202 const ElementType* elements, | 252 const ElementType* elements, |
203 BoundsChecker* bounds_checker) { | 253 BoundsChecker* bounds_checker) { |
204 for (uint32_t i = 0; i < header->num_elements; ++i) { | 254 for (uint32_t i = 0; i < header->num_elements; ++i) { |
| 255 if (IsNonNullableValidationEnabled() && !element_nullable && |
| 256 !elements[i].offset) { |
| 257 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_NULL_POINTER); |
| 258 return false; |
| 259 } |
205 if (!ValidateEncodedPointer(&elements[i].offset)) { | 260 if (!ValidateEncodedPointer(&elements[i].offset)) { |
206 ReportValidationError(VALIDATION_ERROR_ILLEGAL_POINTER); | 261 ReportValidationError(VALIDATION_ERROR_ILLEGAL_POINTER); |
207 return false; | 262 return false; |
208 } | 263 } |
209 if (!P::Validate(DecodePointerRaw(&elements[i].offset), bounds_checker)) | 264 if (!ValidateCaller<P, ElementValidateParams>::Run( |
| 265 DecodePointerRaw(&elements[i].offset), bounds_checker)) { |
210 return false; | 266 return false; |
| 267 } |
211 } | 268 } |
212 return true; | 269 return true; |
213 } | 270 } |
| 271 |
| 272 private: |
| 273 template <typename T, typename Params> |
| 274 struct ValidateCaller { |
| 275 static bool Run(const void* data, BoundsChecker* bounds_checker) { |
| 276 MOJO_COMPILE_ASSERT( |
| 277 (IsSame<Params, NoValidateParams>::value), |
| 278 Struct_type_should_not_have_array_validate_params); |
| 279 |
| 280 return T::Validate(data, bounds_checker); |
| 281 } |
| 282 }; |
| 283 |
| 284 template <typename T, typename Params> |
| 285 struct ValidateCaller<Array_Data<T>, Params> { |
| 286 static bool Run(const void* data, BoundsChecker* bounds_checker) { |
| 287 return Array_Data<T>::template Validate<Params>(data, bounds_checker); |
| 288 } |
| 289 }; |
214 }; | 290 }; |
215 | 291 |
216 template <typename T> | 292 template <typename T> |
217 class Array_Data { | 293 class Array_Data { |
218 public: | 294 public: |
219 typedef ArrayDataTraits<T> Traits; | 295 typedef ArrayDataTraits<T> Traits; |
220 typedef typename Traits::StorageType StorageType; | 296 typedef typename Traits::StorageType StorageType; |
221 typedef typename Traits::Ref Ref; | 297 typedef typename Traits::Ref Ref; |
222 typedef typename Traits::ConstRef ConstRef; | 298 typedef typename Traits::ConstRef ConstRef; |
223 typedef ArraySerializationHelper<T, IsHandle<T>::value> Helper; | 299 typedef ArraySerializationHelper<T, IsHandle<T>::value> Helper; |
224 | 300 |
225 static Array_Data<T>* New(size_t num_elements, Buffer* buf) { | 301 static Array_Data<T>* New(size_t num_elements, Buffer* buf) { |
226 size_t num_bytes = sizeof(Array_Data<T>) + | 302 size_t num_bytes = sizeof(Array_Data<T>) + |
227 Traits::GetStorageSize(num_elements); | 303 Traits::GetStorageSize(num_elements); |
228 return new (buf->Allocate(num_bytes)) Array_Data<T>(num_bytes, | 304 return new (buf->Allocate(num_bytes)) Array_Data<T>(num_bytes, |
229 num_elements); | 305 num_elements); |
230 } | 306 } |
231 | 307 |
232 // If expected_num_elements is not zero, the actual number of elements in the | 308 template <typename Params> |
233 // header must match that value or the message is rejected. | 309 static bool Validate(const void* data, BoundsChecker* bounds_checker) { |
234 static bool Validate(const void* data, | |
235 BoundsChecker* bounds_checker, | |
236 uint32_t expected_num_elements = 0) { | |
237 if (!data) | 310 if (!data) |
238 return true; | 311 return true; |
239 if (!IsAligned(data)) { | 312 if (!IsAligned(data)) { |
240 ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT); | 313 ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT); |
241 return false; | 314 return false; |
242 } | 315 } |
243 if (!bounds_checker->IsValidRange(data, sizeof(ArrayHeader))) { | 316 if (!bounds_checker->IsValidRange(data, sizeof(ArrayHeader))) { |
244 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); | 317 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); |
245 return false; | 318 return false; |
246 } | 319 } |
247 const ArrayHeader* header = static_cast<const ArrayHeader*>(data); | 320 const ArrayHeader* header = static_cast<const ArrayHeader*>(data); |
248 if (header->num_bytes < (sizeof(Array_Data<T>) + | 321 if (header->num_bytes < (sizeof(Array_Data<T>) + |
249 Traits::GetStorageSize(header->num_elements))) { | 322 Traits::GetStorageSize(header->num_elements))) { |
250 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER); | 323 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER); |
251 return false; | 324 return false; |
252 } | 325 } |
253 if (expected_num_elements != 0 && | 326 if (Params::expected_num_elements != 0 && |
254 header->num_elements != expected_num_elements) { | 327 header->num_elements != Params::expected_num_elements) { |
255 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER); | 328 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER); |
256 return false; | 329 return false; |
257 } | 330 } |
258 if (!bounds_checker->ClaimMemory(data, header->num_bytes)) { | 331 if (!bounds_checker->ClaimMemory(data, header->num_bytes)) { |
259 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); | 332 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); |
260 return false; | 333 return false; |
261 } | 334 } |
262 | 335 |
263 const Array_Data<T>* object = static_cast<const Array_Data<T>*>(data); | 336 const Array_Data<T>* object = static_cast<const Array_Data<T>*>(data); |
264 return Helper::ValidateElements(&object->header_, object->storage(), | 337 return Helper::template ValidateElements< |
265 bounds_checker); | 338 Params::element_nullable, typename Params::ElementValidateParams>( |
| 339 &object->header_, object->storage(), bounds_checker); |
266 } | 340 } |
267 | 341 |
268 size_t size() const { return header_.num_elements; } | 342 size_t size() const { return header_.num_elements; } |
269 | 343 |
270 Ref at(size_t offset) { | 344 Ref at(size_t offset) { |
271 MOJO_DCHECK(offset < static_cast<size_t>(header_.num_elements)); | 345 MOJO_DCHECK(offset < static_cast<size_t>(header_.num_elements)); |
272 return Traits::ToRef(storage(), offset); | 346 return Traits::ToRef(storage(), offset); |
273 } | 347 } |
274 | 348 |
275 ConstRef at(size_t offset) const { | 349 ConstRef at(size_t offset) const { |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 }; | 459 }; |
386 | 460 |
387 template <> struct WrapperTraits<String, false> { | 461 template <> struct WrapperTraits<String, false> { |
388 typedef String_Data* DataType; | 462 typedef String_Data* DataType; |
389 }; | 463 }; |
390 | 464 |
391 } // namespace internal | 465 } // namespace internal |
392 } // namespace mojo | 466 } // namespace mojo |
393 | 467 |
394 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ | 468 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ |
OLD | NEW |