| Index: mojo/public/cpp/bindings/lib/array_internal.h
|
| diff --git a/mojo/public/cpp/bindings/lib/array_internal.h b/mojo/public/cpp/bindings/lib/array_internal.h
|
| index f1b34ad72035a883340d88f6aa47f0329e324284..a4e36a7caad28203819f596e580a5953aa60ad34 100644
|
| --- a/mojo/public/cpp/bindings/lib/array_internal.h
|
| +++ b/mojo/public/cpp/bindings/lib/array_internal.h
|
| @@ -23,14 +23,22 @@ class String;
|
|
|
| namespace internal {
|
|
|
| +// std::numeric_limits<uint32_t>::max() is not a compile-time constant (until
|
| +// C++11).
|
| +const uint32_t kMaxUint32 = 0xFFFFFFFF;
|
| +
|
| template <typename T>
|
| struct ArrayDataTraits {
|
| typedef T StorageType;
|
| typedef T& Ref;
|
| typedef T const& ConstRef;
|
|
|
| - static size_t GetStorageSize(size_t num_elements) {
|
| - return sizeof(StorageType) * num_elements;
|
| + static const uint32_t kMaxNumElements =
|
| + (kMaxUint32 - sizeof(ArrayHeader)) / sizeof(StorageType);
|
| +
|
| + static uint32_t GetStorageSize(uint32_t num_elements) {
|
| + MOJO_DCHECK(num_elements <= kMaxNumElements);
|
| + return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements;
|
| }
|
| static Ref ToRef(StorageType* storage, size_t offset) {
|
| return storage[offset];
|
| @@ -46,8 +54,12 @@ struct ArrayDataTraits<P*> {
|
| typedef P*& Ref;
|
| typedef P* const& ConstRef;
|
|
|
| - static size_t GetStorageSize(size_t num_elements) {
|
| - return sizeof(StorageType) * num_elements;
|
| + static const uint32_t kMaxNumElements =
|
| + (kMaxUint32 - sizeof(ArrayHeader)) / sizeof(StorageType);
|
| +
|
| + static uint32_t GetStorageSize(uint32_t num_elements) {
|
| + MOJO_DCHECK(num_elements <= kMaxNumElements);
|
| + return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements;
|
| }
|
| static Ref ToRef(StorageType* storage, size_t offset) {
|
| return storage[offset].ptr;
|
| @@ -63,8 +75,12 @@ struct ArrayDataTraits<Array_Data<T>*> {
|
| typedef Array_Data<T>*& Ref;
|
| typedef Array_Data<T>* const& ConstRef;
|
|
|
| - static size_t GetStorageSize(size_t num_elements) {
|
| - return sizeof(StorageType) * num_elements;
|
| + static const uint32_t kMaxNumElements =
|
| + (kMaxUint32 - sizeof(ArrayHeader)) / sizeof(StorageType);
|
| +
|
| + static uint32_t GetStorageSize(uint32_t num_elements) {
|
| + MOJO_DCHECK(num_elements <= kMaxNumElements);
|
| + return sizeof(ArrayHeader) + sizeof(StorageType) * num_elements;
|
| }
|
| static Ref ToRef(StorageType* storage, size_t offset) {
|
| return storage[offset].ptr;
|
| @@ -97,12 +113,15 @@ struct ArrayDataTraits<bool> {
|
| uint8_t mask_;
|
| };
|
|
|
| + // Because each element consumes only 1/8 byte.
|
| + static const uint32_t kMaxNumElements = kMaxUint32;
|
| +
|
| typedef uint8_t StorageType;
|
| typedef BitRef Ref;
|
| typedef bool ConstRef;
|
|
|
| - static size_t GetStorageSize(size_t num_elements) {
|
| - return ((num_elements + 7) / 8);
|
| + static uint32_t GetStorageSize(uint32_t num_elements) {
|
| + return sizeof(ArrayHeader) + ((num_elements + 7) / 8);
|
| }
|
| static BitRef ToRef(StorageType* storage, size_t offset) {
|
| return BitRef(&storage[offset / 8], 1 << (offset % 8));
|
| @@ -298,11 +317,16 @@ class Array_Data {
|
| typedef typename Traits::ConstRef ConstRef;
|
| typedef ArraySerializationHelper<T, IsHandle<T>::value> Helper;
|
|
|
| + // Returns NULL if |num_elements| or the corresponding storage size cannot be
|
| + // stored in uint32_t.
|
| static Array_Data<T>* New(size_t num_elements, Buffer* buf) {
|
| - size_t num_bytes = sizeof(Array_Data<T>) +
|
| - Traits::GetStorageSize(num_elements);
|
| - return new (buf->Allocate(num_bytes)) Array_Data<T>(num_bytes,
|
| - num_elements);
|
| + if (num_elements > Traits::kMaxNumElements)
|
| + return NULL;
|
| +
|
| + uint32_t num_bytes =
|
| + Traits::GetStorageSize(static_cast<uint32_t>(num_elements));
|
| + return new (buf->Allocate(num_bytes)) Array_Data<T>(
|
| + num_bytes, static_cast<uint32_t>(num_elements));
|
| }
|
|
|
| template <typename Params>
|
| @@ -318,8 +342,8 @@ class Array_Data {
|
| return false;
|
| }
|
| const ArrayHeader* header = static_cast<const ArrayHeader*>(data);
|
| - if (header->num_bytes < (sizeof(Array_Data<T>) +
|
| - Traits::GetStorageSize(header->num_elements))) {
|
| + if (header->num_elements > Traits::kMaxNumElements ||
|
| + header->num_bytes < Traits::GetStorageSize(header->num_elements)) {
|
| ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER);
|
| return false;
|
| }
|
| @@ -370,9 +394,9 @@ class Array_Data {
|
| }
|
|
|
| private:
|
| - Array_Data(size_t num_bytes, size_t num_elements) {
|
| - header_.num_bytes = static_cast<uint32_t>(num_bytes);
|
| - header_.num_elements = static_cast<uint32_t>(num_elements);
|
| + Array_Data(uint32_t num_bytes, uint32_t num_elements) {
|
| + header_.num_bytes = num_bytes;
|
| + header_.num_elements = num_elements;
|
| }
|
| ~Array_Data() {}
|
|
|
|
|