Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(722)

Unified Diff: mojo/public/cpp/bindings/lib/array_internal.h

Issue 466613002: Add validation logic for non-nullable types. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | mojo/public/cpp/bindings/lib/array_internal.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 190f6da9ea1c95be544fd21e082968e2a2e51630..f74c857a35930e243010c459d1806c4694db4b06 100644
--- a/mojo/public/cpp/bindings/lib/array_internal.h
+++ b/mojo/public/cpp/bindings/lib/array_internal.h
@@ -8,10 +8,12 @@
#include <new>
#include <vector>
+#include "mojo/public/c/system/macros.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/lib/buffer.h"
+#include "mojo/public/cpp/bindings/lib/template_util.h"
#include "mojo/public/cpp/bindings/lib/validation_errors.h"
#include "mojo/public/cpp/environment/logging.h"
@@ -110,11 +112,32 @@ struct ArrayDataTraits<bool> {
}
};
+// Array type information needed for valdiation.
+template <uint32_t in_expected_num_elements,
+ bool in_element_nullable,
+ typename InElementValidateParams>
+class ArrayValidateParams {
+ public:
+ // Validation information for elements. It is either another specialization of
+ // ArrayValidateParams (if elements are arrays) or NoValidateParams.
+ typedef InElementValidateParams ElementValidateParams;
+
+ // If |expected_num_elements| is not 0, the array is expected to have exactly
+ // that number of elements.
+ static const uint32_t expected_num_elements = in_expected_num_elements;
+ // Whether the elements are nullable.
+ static const bool element_nullable = in_element_nullable;
+};
+
+// NoValidateParams is used to indicate the end of an ArrayValidateParams chain.
+class NoValidateParams {
+};
+
// What follows is code to support the serialization of Array_Data<T>. There
// are two interesting cases: arrays of primitives and arrays of objects.
// Arrays of objects are represented as arrays of pointers to objects.
-template <typename T, bool kIsHandle> struct ArraySerializationHelper;
+template <typename T, bool is_handle> struct ArraySerializationHelper;
template <typename T>
struct ArraySerializationHelper<T, false> {
@@ -130,9 +153,15 @@ struct ArraySerializationHelper<T, false> {
std::vector<Handle>* handles) {
}
+ template <bool element_nullable, typename ElementValidateParams>
static bool ValidateElements(const ArrayHeader* header,
const ElementType* elements,
BoundsChecker* bounds_checker) {
+ MOJO_COMPILE_ASSERT(!element_nullable,
+ Primitive_type_should_be_non_nullable);
+ MOJO_COMPILE_ASSERT(
+ (IsSame<ElementValidateParams, NoValidateParams>::value),
+ Primitive_type_should_not_have_array_validate_params);
return true;
}
};
@@ -149,9 +178,27 @@ struct ArraySerializationHelper<Handle, true> {
ElementType* elements,
std::vector<Handle>* handles);
+ template <bool element_nullable, typename ElementValidateParams>
static bool ValidateElements(const ArrayHeader* header,
const ElementType* elements,
- BoundsChecker* bounds_checker);
+ BoundsChecker* bounds_checker) {
+ MOJO_COMPILE_ASSERT(
+ (IsSame<ElementValidateParams, NoValidateParams>::value),
+ Handle_type_should_not_have_array_validate_params);
+
+ for (uint32_t i = 0; i < header->num_elements; ++i) {
+ if (IsNonNullableValidationEnabled() && !element_nullable &&
+ elements[i].value() == kEncodedInvalidHandleValue) {
+ ReportValidationError(VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE);
+ return false;
+ }
+ if (!bounds_checker->ClaimHandle(elements[i])) {
+ ReportValidationError(VALIDATION_ERROR_ILLEGAL_HANDLE);
+ return false;
+ }
+ }
+ return true;
+ }
};
template <typename H>
@@ -172,11 +219,13 @@ struct ArraySerializationHelper<H, true> {
header, elements, handles);
}
+ template <bool element_nullable, typename ElementValidateParams>
static bool ValidateElements(const ArrayHeader* header,
const ElementType* elements,
BoundsChecker* bounds_checker) {
- return ArraySerializationHelper<Handle, true>::ValidateElements(
- header, elements, bounds_checker);
+ return ArraySerializationHelper<Handle, true>::
+ ValidateElements<element_nullable, ElementValidateParams>(
+ header, elements, bounds_checker);
}
};
@@ -198,19 +247,46 @@ struct ArraySerializationHelper<P*, false> {
Decode(&elements[i], handles);
}
+ template <bool element_nullable, typename ElementValidateParams>
static bool ValidateElements(const ArrayHeader* header,
const ElementType* elements,
BoundsChecker* bounds_checker) {
for (uint32_t i = 0; i < header->num_elements; ++i) {
+ if (IsNonNullableValidationEnabled() && !element_nullable &&
+ !elements[i].offset) {
+ ReportValidationError(VALIDATION_ERROR_UNEXPECTED_NULL_POINTER);
+ return false;
+ }
if (!ValidateEncodedPointer(&elements[i].offset)) {
ReportValidationError(VALIDATION_ERROR_ILLEGAL_POINTER);
return false;
}
- if (!P::Validate(DecodePointerRaw(&elements[i].offset), bounds_checker))
+ if (!ValidateCaller<P, ElementValidateParams>::Run(
+ DecodePointerRaw(&elements[i].offset), bounds_checker)) {
return false;
+ }
}
return true;
}
+
+ private:
+ template <typename T, typename Params>
+ struct ValidateCaller {
+ static bool Run(const void* data, BoundsChecker* bounds_checker) {
+ MOJO_COMPILE_ASSERT(
+ (IsSame<Params, NoValidateParams>::value),
+ Struct_type_should_not_have_array_validate_params);
+
+ return T::Validate(data, bounds_checker);
+ }
+ };
+
+ template <typename T, typename Params>
+ struct ValidateCaller<Array_Data<T>, Params> {
+ static bool Run(const void* data, BoundsChecker* bounds_checker) {
+ return Array_Data<T>::template Validate<Params>(data, bounds_checker);
+ }
+ };
};
template <typename T>
@@ -229,11 +305,8 @@ class Array_Data {
num_elements);
}
- // If expected_num_elements is not zero, the actual number of elements in the
- // header must match that value or the message is rejected.
- static bool Validate(const void* data,
- BoundsChecker* bounds_checker,
- uint32_t expected_num_elements = 0) {
+ template <typename Params>
+ static bool Validate(const void* data, BoundsChecker* bounds_checker) {
if (!data)
return true;
if (!IsAligned(data)) {
@@ -250,8 +323,8 @@ class Array_Data {
ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER);
return false;
}
- if (expected_num_elements != 0 &&
- header->num_elements != expected_num_elements) {
+ if (Params::expected_num_elements != 0 &&
+ header->num_elements != Params::expected_num_elements) {
ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER);
return false;
}
@@ -261,8 +334,9 @@ class Array_Data {
}
const Array_Data<T>* object = static_cast<const Array_Data<T>*>(data);
- return Helper::ValidateElements(&object->header_, object->storage(),
- bounds_checker);
+ return Helper::template ValidateElements<
+ Params::element_nullable, typename Params::ElementValidateParams>(
+ &object->header_, object->storage(), bounds_checker);
}
size_t size() const { return header_.num_elements; }
« no previous file with comments | « no previous file | mojo/public/cpp/bindings/lib/array_internal.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698