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 5e7dea878ef399863ca019e202be1714fd29df3e..c1cf3e47c1089cbb828d0a6ceba657d060ca2bc7 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/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/lib/buffer.h" |
namespace mojo { |
@@ -110,6 +111,12 @@ struct ArraySerializationHelper<T, false> { |
Message* message) { |
return true; |
} |
+ |
+ static bool ValidateElements(const ArrayHeader* header, |
+ const ElementType* elements, |
+ BoundsChecker* bounds_checker) { |
+ return true; |
+ } |
}; |
template <> |
@@ -123,6 +130,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> |
@@ -142,6 +153,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> |
@@ -164,6 +182,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> |
@@ -182,6 +212,26 @@ class Array_Data { |
num_elements); |
} |
+ static bool Validate(const void* data, BoundsChecker* bounds_checker) { |
+ if (!data) |
+ return true; |
+ if (!IsAligned(data)) |
+ return false; |
+ if (!bounds_checker->IsValidRange(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) { |