1 // Copyright 2015 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_UTIL_H_ 6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_UTIL_H_ 7 8 #include <stdint.h> 9 10 #include "base/component_export.h" 11 #include "mojo/public/cpp/bindings/lib/bindings_internal.h" 12 #include "mojo/public/cpp/bindings/lib/serialization_util.h" 13 #include "mojo/public/cpp/bindings/lib/validate_params.h" 14 #include "mojo/public/cpp/bindings/lib/validation_context.h" 15 #include "mojo/public/cpp/bindings/lib/validation_errors.h" 16 #include "mojo/public/cpp/bindings/message.h" 17 18 namespace mojo { 19 namespace internal { 20 21 // Calls ReportValidationError() with a constructed error string. 22 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 23 void ReportNonNullableValidationError(ValidationContext* validation_context, 24 ValidationError error, 25 int field_index); 26 27 // Checks whether decoding the pointer will overflow and produce a pointer 28 // smaller than |offset|. 29 inline bool ValidateEncodedPointer(const uint64_t* offset) { 30 // - Make sure |*offset| is no more than 32-bits. 31 // - Cast |offset| to uintptr_t so overflow behavior is well defined across 32 // 32-bit and 64-bit systems. 33 return *offset <= std::numeric_limits<uint32_t>::max() && 34 (reinterpret_cast<uintptr_t>(offset) + 35 static_cast<uint32_t>(*offset) >= 36 reinterpret_cast<uintptr_t>(offset)); 37 } 38 39 template <typename T> 40 bool ValidatePointer(const Pointer<T>& input, 41 ValidationContext* validation_context) { 42 bool result = ValidateEncodedPointer(&input.offset); 43 if (!result) 44 ReportValidationError(validation_context, VALIDATION_ERROR_ILLEGAL_POINTER); 45 46 return result; 47 } 48 49 // Validates that |data| contains a valid struct header, in terms of alignment 50 // and size (i.e., the |num_bytes| field of the header is sufficient for storing 51 // the header itself). Besides, it checks that the memory range 52 // [data, data + num_bytes) is not marked as occupied by other objects in 53 // |validation_context|. On success, the memory range is marked as occupied. 54 // Note: Does not verify |version| or that |num_bytes| is correct for the 55 // claimed version. 56 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 57 bool ValidateStructHeaderAndClaimMemory(const void* data, 58 ValidationContext* validation_context); 59 60 // Validates that |data| contains a valid union header, in terms of alignment 61 // and size. It checks that the memory range [data, data + kUnionDataSize) is 62 // not marked as occupied by other objects in |validation_context|. On success, 63 // the memory range is marked as occupied. 64 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 65 bool ValidateNonInlinedUnionHeaderAndClaimMemory( 66 const void* data, 67 ValidationContext* validation_context); 68 69 // Validates that the message is a request which doesn't expect a response. 70 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 71 bool ValidateMessageIsRequestWithoutResponse( 72 const Message* message, 73 ValidationContext* validation_context); 74 75 // Validates that the message is a request expecting a response. 76 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 77 bool ValidateMessageIsRequestExpectingResponse( 78 const Message* message, 79 ValidationContext* validation_context); 80 81 // Validates that the message is a response. 82 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 83 bool ValidateMessageIsResponse(const Message* message, 84 ValidationContext* validation_context); 85 86 // Validates that the message payload is a valid struct of type ParamsType. 87 template <typename ParamsType> 88 bool ValidateMessagePayload(const Message* message, 89 ValidationContext* validation_context) { 90 return ParamsType::Validate(message->payload(), validation_context); 91 } 92 93 // The following Validate.*NonNullable() functions validate that the given 94 // |input| is not null/invalid. 95 template <typename T> 96 bool ValidatePointerNonNullable(const T& input, 97 int field_index, 98 ValidationContext* validation_context) { 99 if (input.offset) 100 return true; 101 ReportNonNullableValidationError(validation_context, 102 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, 103 field_index); 104 return false; 105 } 106 107 template <typename T> 108 bool ValidateInlinedUnionNonNullable(const T& input, 109 int field_index, 110 ValidationContext* validation_context) { 111 if (!input.is_null()) 112 return true; 113 ReportNonNullableValidationError(validation_context, 114 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, 115 field_index); 116 return false; 117 } 118 119 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 120 bool IsHandleOrInterfaceValid(const AssociatedInterface_Data& input); 121 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 122 bool IsHandleOrInterfaceValid(const AssociatedEndpointHandle_Data& input); 123 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 124 bool IsHandleOrInterfaceValid(const Interface_Data& input); 125 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 126 bool IsHandleOrInterfaceValid(const Handle_Data& input); 127 128 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 129 bool ValidateHandleOrInterfaceNonNullable( 130 const AssociatedInterface_Data& input, 131 int field_index, 132 ValidationContext* validation_context); 133 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 134 bool ValidateHandleOrInterfaceNonNullable( 135 const AssociatedEndpointHandle_Data& input, 136 int field_index, 137 ValidationContext* validation_context); 138 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 139 bool ValidateHandleOrInterfaceNonNullable( 140 const Interface_Data& input, 141 int field_index, 142 ValidationContext* validation_context); 143 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 144 bool ValidateHandleOrInterfaceNonNullable( 145 const Handle_Data& input, 146 int field_index, 147 ValidationContext* validation_context); 148 149 template <typename T> 150 bool ValidateContainer(const Pointer<T>& input, 151 ValidationContext* validation_context, 152 const ContainerValidateParams* validate_params) { 153 ValidationContext::ScopedDepthTracker depth_tracker(validation_context); 154 if (validation_context->ExceedsMaxDepth()) { 155 ReportValidationError(validation_context, 156 VALIDATION_ERROR_MAX_RECURSION_DEPTH); 157 return false; 158 } 159 return ValidatePointer(input, validation_context) && 160 T::Validate(input.Get(), validation_context, validate_params); 161 } 162 163 template <typename T> 164 bool ValidateStruct(const Pointer<T>& input, 165 ValidationContext* validation_context) { 166 ValidationContext::ScopedDepthTracker depth_tracker(validation_context); 167 if (validation_context->ExceedsMaxDepth()) { 168 ReportValidationError(validation_context, 169 VALIDATION_ERROR_MAX_RECURSION_DEPTH); 170 return false; 171 } 172 return ValidatePointer(input, validation_context) && 173 T::Validate(input.Get(), validation_context); 174 } 175 176 template <typename T> 177 bool ValidateInlinedUnion(const T& input, 178 ValidationContext* validation_context) { 179 ValidationContext::ScopedDepthTracker depth_tracker(validation_context); 180 if (validation_context->ExceedsMaxDepth()) { 181 ReportValidationError(validation_context, 182 VALIDATION_ERROR_MAX_RECURSION_DEPTH); 183 return false; 184 } 185 return T::Validate(&input, validation_context, true); 186 } 187 188 template <typename T> 189 bool ValidateNonInlinedUnion(const Pointer<T>& input, 190 ValidationContext* validation_context) { 191 ValidationContext::ScopedDepthTracker depth_tracker(validation_context); 192 if (validation_context->ExceedsMaxDepth()) { 193 ReportValidationError(validation_context, 194 VALIDATION_ERROR_MAX_RECURSION_DEPTH); 195 return false; 196 } 197 return ValidatePointer(input, validation_context) && 198 T::Validate(input.Get(), validation_context, false); 199 } 200 201 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 202 bool ValidateHandleOrInterface(const AssociatedInterface_Data& input, 203 ValidationContext* validation_context); 204 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 205 bool ValidateHandleOrInterface(const AssociatedEndpointHandle_Data& input, 206 ValidationContext* validation_context); 207 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 208 bool ValidateHandleOrInterface(const Interface_Data& input, 209 ValidationContext* validation_context); 210 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 211 bool ValidateHandleOrInterface(const Handle_Data& input, 212 ValidationContext* validation_context); 213 214 } // namespace internal 215 } // namespace mojo 216 217 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_UTIL_H_ 218