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 865bf1cc8647e82a949ade03dac505887266c184..c526735e41b680525cbfd58432a8a018ce9fb4c3 100644 |
--- a/mojo/public/cpp/bindings/lib/array_internal.h |
+++ b/mojo/public/cpp/bindings/lib/array_internal.h |
@@ -10,6 +10,7 @@ |
#include "mojo/public/cpp/bindings/buffer.h" |
#include "mojo/public/cpp/bindings/lib/bindings_internal.h" |
#include "mojo/public/cpp/bindings/lib/bindings_serialization.h" |
+#include "mojo/public/cpp/bindings/lib/bounds_checker.h" |
#include "mojo/public/cpp/bindings/passable.h" |
namespace mojo { |
@@ -129,6 +130,12 @@ struct ArraySerializationHelper<T, false> { |
Message* message) { |
return true; |
} |
+ |
+ static bool ValidateElements(const ArrayHeader* header, |
+ const ElementType* elements, |
+ BoundsChecker* bounds_checker) { |
+ return true; |
+ } |
}; |
template <> |
@@ -156,6 +163,10 @@ struct ArraySerializationHelper<Handle, true> { |
static bool DecodePointersAndHandles(const ArrayHeader* header, |
ElementType* elements, |
Message* message); |
+ |
+ static bool ValidateElements(const ArrayHeader* header, |
+ const ElementType* elements, |
+ BoundsChecker* bounds_checker); |
}; |
template <typename H> |
@@ -193,6 +204,13 @@ struct ArraySerializationHelper<H, true> { |
return ArraySerializationHelper<Handle, true>::DecodePointersAndHandles( |
header, elements, message); |
} |
+ |
+ static bool ValidateElements(const ArrayHeader* header, |
+ const ElementType* elements, |
+ BoundsChecker* bounds_checker) { |
+ return ArraySerializationHelper<Handle, true>::ValidateElements( |
+ header, elements, bounds_checker); |
+ } |
}; |
template <typename P> |
@@ -245,6 +263,18 @@ struct ArraySerializationHelper<P*, false> { |
} |
return true; |
} |
+ |
+ static bool ValidateElements(const ArrayHeader* header, |
+ const ElementType* elements, |
+ BoundsChecker* bounds_checker) { |
+ for (uint32_t i = 0; i < header->num_elements; ++i) { |
+ if (!ValidateEncodedPointer(&elements[i].offset) || |
+ !P::Validate(DecodePointerRaw(&elements[i].offset), bounds_checker)) { |
+ return false; |
+ } |
+ } |
+ return true; |
+ } |
}; |
template <typename T> |
@@ -269,6 +299,26 @@ class Array_Data { |
static_cast<Array_Data*>(address)->CloseHandles(); |
} |
+ static bool Validate(const void* data, BoundsChecker* bounds_checker) { |
+ if (!data) |
+ return true; |
+ if (!IsAligned(data)) |
+ return false; |
+ if (!bounds_checker->IsWithinBounds(data, sizeof(ArrayHeader))) |
+ return false; |
+ const ArrayHeader* header = static_cast<const ArrayHeader*>(data); |
+ if (header->num_bytes < (sizeof(Array_Data<T>) + |
+ Traits::GetStorageSize(header->num_elements))) { |
+ return false; |
+ } |
+ if (!bounds_checker->ClaimMemory(data, header->num_bytes)) |
+ return false; |
+ |
+ const Array_Data<T>* object = static_cast<const Array_Data<T>*>(data); |
+ return Helper::ValidateElements(&object->header_, object->storage(), |
+ bounds_checker); |
+ } |
+ |
size_t size() const { return header_.num_elements; } |
Ref at(size_t offset) { |