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/c/system/macros.h" |
12 #include "mojo/public/cpp/bindings/lib/bindings_internal.h" | 12 #include "mojo/public/cpp/bindings/lib/bindings_internal.h" |
13 #include "mojo/public/cpp/bindings/lib/bindings_serialization.h" | 13 #include "mojo/public/cpp/bindings/lib/bindings_serialization.h" |
14 #include "mojo/public/cpp/bindings/lib/bounds_checker.h" | 14 #include "mojo/public/cpp/bindings/lib/bounds_checker.h" |
15 #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" | 16 #include "mojo/public/cpp/bindings/lib/template_util.h" |
17 #include "mojo/public/cpp/bindings/lib/validation_errors.h" | 17 #include "mojo/public/cpp/bindings/lib/validation_errors.h" |
18 #include "mojo/public/cpp/environment/logging.h" | 18 #include "mojo/public/cpp/environment/logging.h" |
19 | 19 |
20 namespace mojo { | 20 namespace mojo { |
21 template <typename T> class Array; | 21 template <typename T> class Array; |
22 class String; | 22 class String; |
23 | 23 |
24 namespace internal { | 24 namespace internal { |
25 | 25 |
| 26 // std::numeric_limits<uint32_t>::max() is not a compile-time constant (until |
| 27 // C++11). |
| 28 const uint32_t kMaxUint32 = 0xFFFFFFFF; |
| 29 |
26 template <typename T> | 30 template <typename T> |
27 struct ArrayDataTraits { | 31 struct ArrayDataTraits { |
28 typedef T StorageType; | 32 typedef T StorageType; |
29 typedef T& Ref; | 33 typedef T& Ref; |
30 typedef T const& ConstRef; | 34 typedef T const& ConstRef; |
31 | 35 |
32 static size_t GetStorageSize(size_t num_elements) { | 36 static const uint32_t kMaxNumElements = |
33 return sizeof(StorageType) * num_elements; | 37 (kMaxUint32 - sizeof(ArrayHeader)) / sizeof(StorageType); |
| 38 |
| 39 static uint32_t GetStorageSize(uint32_t num_elements) { |
| 40 MOJO_DCHECK(num_elements <= kMaxNumElements); |
| 41 return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements; |
34 } | 42 } |
35 static Ref ToRef(StorageType* storage, size_t offset) { | 43 static Ref ToRef(StorageType* storage, size_t offset) { |
36 return storage[offset]; | 44 return storage[offset]; |
37 } | 45 } |
38 static ConstRef ToConstRef(const StorageType* storage, size_t offset) { | 46 static ConstRef ToConstRef(const StorageType* storage, size_t offset) { |
39 return storage[offset]; | 47 return storage[offset]; |
40 } | 48 } |
41 }; | 49 }; |
42 | 50 |
43 template <typename P> | 51 template <typename P> |
44 struct ArrayDataTraits<P*> { | 52 struct ArrayDataTraits<P*> { |
45 typedef StructPointer<P> StorageType; | 53 typedef StructPointer<P> StorageType; |
46 typedef P*& Ref; | 54 typedef P*& Ref; |
47 typedef P* const& ConstRef; | 55 typedef P* const& ConstRef; |
48 | 56 |
49 static size_t GetStorageSize(size_t num_elements) { | 57 static const uint32_t kMaxNumElements = |
50 return sizeof(StorageType) * num_elements; | 58 (kMaxUint32 - sizeof(ArrayHeader)) / sizeof(StorageType); |
| 59 |
| 60 static uint32_t GetStorageSize(uint32_t num_elements) { |
| 61 MOJO_DCHECK(num_elements <= kMaxNumElements); |
| 62 return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements; |
51 } | 63 } |
52 static Ref ToRef(StorageType* storage, size_t offset) { | 64 static Ref ToRef(StorageType* storage, size_t offset) { |
53 return storage[offset].ptr; | 65 return storage[offset].ptr; |
54 } | 66 } |
55 static ConstRef ToConstRef(const StorageType* storage, size_t offset) { | 67 static ConstRef ToConstRef(const StorageType* storage, size_t offset) { |
56 return storage[offset].ptr; | 68 return storage[offset].ptr; |
57 } | 69 } |
58 }; | 70 }; |
59 | 71 |
60 template <typename T> | 72 template <typename T> |
61 struct ArrayDataTraits<Array_Data<T>*> { | 73 struct ArrayDataTraits<Array_Data<T>*> { |
62 typedef ArrayPointer<T> StorageType; | 74 typedef ArrayPointer<T> StorageType; |
63 typedef Array_Data<T>*& Ref; | 75 typedef Array_Data<T>*& Ref; |
64 typedef Array_Data<T>* const& ConstRef; | 76 typedef Array_Data<T>* const& ConstRef; |
65 | 77 |
66 static size_t GetStorageSize(size_t num_elements) { | 78 static const uint32_t kMaxNumElements = |
67 return sizeof(StorageType) * num_elements; | 79 (kMaxUint32 - sizeof(ArrayHeader)) / sizeof(StorageType); |
| 80 |
| 81 static uint32_t GetStorageSize(uint32_t num_elements) { |
| 82 MOJO_DCHECK(num_elements <= kMaxNumElements); |
| 83 return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements; |
68 } | 84 } |
69 static Ref ToRef(StorageType* storage, size_t offset) { | 85 static Ref ToRef(StorageType* storage, size_t offset) { |
70 return storage[offset].ptr; | 86 return storage[offset].ptr; |
71 } | 87 } |
72 static ConstRef ToConstRef(const StorageType* storage, size_t offset) { | 88 static ConstRef ToConstRef(const StorageType* storage, size_t offset) { |
73 return storage[offset].ptr; | 89 return storage[offset].ptr; |
74 } | 90 } |
75 }; | 91 }; |
76 | 92 |
77 // Specialization of Arrays for bools, optimized for space. It has the | 93 // Specialization of Arrays for bools, optimized for space. It has the |
(...skipping 12 matching lines...) Expand all Loading... |
90 BitRef& operator=(const BitRef& value); | 106 BitRef& operator=(const BitRef& value); |
91 operator bool() const; | 107 operator bool() const; |
92 private: | 108 private: |
93 friend struct ArrayDataTraits<bool>; | 109 friend struct ArrayDataTraits<bool>; |
94 BitRef(uint8_t* storage, uint8_t mask); | 110 BitRef(uint8_t* storage, uint8_t mask); |
95 BitRef(); | 111 BitRef(); |
96 uint8_t* storage_; | 112 uint8_t* storage_; |
97 uint8_t mask_; | 113 uint8_t mask_; |
98 }; | 114 }; |
99 | 115 |
| 116 // Because each element consumes only 1/8 byte. |
| 117 static const uint32_t kMaxNumElements = kMaxUint32; |
| 118 |
100 typedef uint8_t StorageType; | 119 typedef uint8_t StorageType; |
101 typedef BitRef Ref; | 120 typedef BitRef Ref; |
102 typedef bool ConstRef; | 121 typedef bool ConstRef; |
103 | 122 |
104 static size_t GetStorageSize(size_t num_elements) { | 123 static uint32_t GetStorageSize(uint32_t num_elements) { |
105 return ((num_elements + 7) / 8); | 124 return sizeof(ArrayHeader) + ((num_elements + 7) / 8); |
106 } | 125 } |
107 static BitRef ToRef(StorageType* storage, size_t offset) { | 126 static BitRef ToRef(StorageType* storage, size_t offset) { |
108 return BitRef(&storage[offset / 8], 1 << (offset % 8)); | 127 return BitRef(&storage[offset / 8], 1 << (offset % 8)); |
109 } | 128 } |
110 static bool ToConstRef(const StorageType* storage, size_t offset) { | 129 static bool ToConstRef(const StorageType* storage, size_t offset) { |
111 return (storage[offset / 8] & (1 << (offset % 8))) != 0; | 130 return (storage[offset / 8] & (1 << (offset % 8))) != 0; |
112 } | 131 } |
113 }; | 132 }; |
114 | 133 |
115 // Array type information needed for valdiation. | 134 // Array type information needed for valdiation. |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 | 310 |
292 template <typename T> | 311 template <typename T> |
293 class Array_Data { | 312 class Array_Data { |
294 public: | 313 public: |
295 typedef ArrayDataTraits<T> Traits; | 314 typedef ArrayDataTraits<T> Traits; |
296 typedef typename Traits::StorageType StorageType; | 315 typedef typename Traits::StorageType StorageType; |
297 typedef typename Traits::Ref Ref; | 316 typedef typename Traits::Ref Ref; |
298 typedef typename Traits::ConstRef ConstRef; | 317 typedef typename Traits::ConstRef ConstRef; |
299 typedef ArraySerializationHelper<T, IsHandle<T>::value> Helper; | 318 typedef ArraySerializationHelper<T, IsHandle<T>::value> Helper; |
300 | 319 |
| 320 // Returns NULL if |num_elements| or the corresponding storage size cannot be |
| 321 // stored in uint32_t. |
301 static Array_Data<T>* New(size_t num_elements, Buffer* buf) { | 322 static Array_Data<T>* New(size_t num_elements, Buffer* buf) { |
302 size_t num_bytes = sizeof(Array_Data<T>) + | 323 if (num_elements > Traits::kMaxNumElements) |
303 Traits::GetStorageSize(num_elements); | 324 return NULL; |
304 return new (buf->Allocate(num_bytes)) Array_Data<T>(num_bytes, | 325 |
305 num_elements); | 326 uint32_t num_bytes = |
| 327 Traits::GetStorageSize(static_cast<uint32_t>(num_elements)); |
| 328 return new (buf->Allocate(num_bytes)) Array_Data<T>( |
| 329 num_bytes, static_cast<uint32_t>(num_elements)); |
306 } | 330 } |
307 | 331 |
308 template <typename Params> | 332 template <typename Params> |
309 static bool Validate(const void* data, BoundsChecker* bounds_checker) { | 333 static bool Validate(const void* data, BoundsChecker* bounds_checker) { |
310 if (!data) | 334 if (!data) |
311 return true; | 335 return true; |
312 if (!IsAligned(data)) { | 336 if (!IsAligned(data)) { |
313 ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT); | 337 ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT); |
314 return false; | 338 return false; |
315 } | 339 } |
316 if (!bounds_checker->IsValidRange(data, sizeof(ArrayHeader))) { | 340 if (!bounds_checker->IsValidRange(data, sizeof(ArrayHeader))) { |
317 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); | 341 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); |
318 return false; | 342 return false; |
319 } | 343 } |
320 const ArrayHeader* header = static_cast<const ArrayHeader*>(data); | 344 const ArrayHeader* header = static_cast<const ArrayHeader*>(data); |
321 if (header->num_bytes < (sizeof(Array_Data<T>) + | 345 if (header->num_elements > Traits::kMaxNumElements || |
322 Traits::GetStorageSize(header->num_elements))) { | 346 header->num_bytes < Traits::GetStorageSize(header->num_elements)) { |
323 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER); | 347 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER); |
324 return false; | 348 return false; |
325 } | 349 } |
326 if (Params::expected_num_elements != 0 && | 350 if (Params::expected_num_elements != 0 && |
327 header->num_elements != Params::expected_num_elements) { | 351 header->num_elements != Params::expected_num_elements) { |
328 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER); | 352 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER); |
329 return false; | 353 return false; |
330 } | 354 } |
331 if (!bounds_checker->ClaimMemory(data, header->num_bytes)) { | 355 if (!bounds_checker->ClaimMemory(data, header->num_bytes)) { |
332 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); | 356 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); |
(...skipping 30 matching lines...) Expand all Loading... |
363 | 387 |
364 void EncodePointersAndHandles(std::vector<Handle>* handles) { | 388 void EncodePointersAndHandles(std::vector<Handle>* handles) { |
365 Helper::EncodePointersAndHandles(&header_, storage(), handles); | 389 Helper::EncodePointersAndHandles(&header_, storage(), handles); |
366 } | 390 } |
367 | 391 |
368 void DecodePointersAndHandles(std::vector<Handle>* handles) { | 392 void DecodePointersAndHandles(std::vector<Handle>* handles) { |
369 Helper::DecodePointersAndHandles(&header_, storage(), handles); | 393 Helper::DecodePointersAndHandles(&header_, storage(), handles); |
370 } | 394 } |
371 | 395 |
372 private: | 396 private: |
373 Array_Data(size_t num_bytes, size_t num_elements) { | 397 Array_Data(uint32_t num_bytes, uint32_t num_elements) { |
374 header_.num_bytes = static_cast<uint32_t>(num_bytes); | 398 header_.num_bytes = num_bytes; |
375 header_.num_elements = static_cast<uint32_t>(num_elements); | 399 header_.num_elements = num_elements; |
376 } | 400 } |
377 ~Array_Data() {} | 401 ~Array_Data() {} |
378 | 402 |
379 internal::ArrayHeader header_; | 403 internal::ArrayHeader header_; |
380 | 404 |
381 // Elements of type internal::ArrayDataTraits<T>::StorageType follow. | 405 // Elements of type internal::ArrayDataTraits<T>::StorageType follow. |
382 }; | 406 }; |
383 MOJO_COMPILE_ASSERT(sizeof(Array_Data<char>) == 8, bad_sizeof_Array_Data); | 407 MOJO_COMPILE_ASSERT(sizeof(Array_Data<char>) == 8, bad_sizeof_Array_Data); |
384 | 408 |
385 // UTF-8 encoded | 409 // UTF-8 encoded |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 }; | 483 }; |
460 | 484 |
461 template <> struct WrapperTraits<String, false> { | 485 template <> struct WrapperTraits<String, false> { |
462 typedef String_Data* DataType; | 486 typedef String_Data* DataType; |
463 }; | 487 }; |
464 | 488 |
465 } // namespace internal | 489 } // namespace internal |
466 } // namespace mojo | 490 } // namespace mojo |
467 | 491 |
468 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ | 492 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ |
OLD | NEW |