| 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 |