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

Side by Side Diff: mojo/public/cpp/bindings/lib/array_internal.h

Issue 486313004: Mojo cpp bindings: More clear checks for array num_bytes and num_elements. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 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 | « no previous file | mojo/public/cpp/bindings/lib/array_serialization.h » ('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_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
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
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
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
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_
OLDNEW
« no previous file with comments | « no previous file | mojo/public/cpp/bindings/lib/array_serialization.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698