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() {} |