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 #include "mojo/public/cpp/bindings/lib/validation_util.h" 6 7 #include <stdint.h> 8 9 #include <limits> 10 11 #include "base/strings/stringprintf.h" 12 #include "mojo/public/cpp/bindings/lib/message_internal.h" 13 #include "mojo/public/cpp/bindings/lib/serialization_util.h" 14 #include "mojo/public/cpp/bindings/lib/validation_errors.h" 15 16 namespace mojo { 17 namespace internal { 18 19 void ReportNonNullableValidationError(ValidationContext* validation_context, 20 ValidationError error, 21 int field_index) { 22 const char* null_or_invalid = 23 error == VALIDATION_ERROR_UNEXPECTED_NULL_POINTER ? "null" : "invalid"; 24 25 std::string error_message = 26 base::StringPrintf("%s field %d", null_or_invalid, field_index); 27 ReportValidationError(validation_context, error, error_message.c_str()); 28 } 29 30 bool ValidateStructHeaderAndClaimMemory(const void* data, 31 ValidationContext* validation_context) { 32 if (!IsAligned(data)) { 33 ReportValidationError(validation_context, 34 VALIDATION_ERROR_MISALIGNED_OBJECT); 35 return false; 36 } 37 if (!validation_context->IsValidRange(data, sizeof(StructHeader))) { 38 ReportValidationError(validation_context, 39 VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); 40 return false; 41 } 42 43 const StructHeader* header = static_cast<const StructHeader*>(data); 44 45 if (header->num_bytes < sizeof(StructHeader)) { 46 ReportValidationError(validation_context, 47 VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); 48 return false; 49 } 50 51 if (!validation_context->ClaimMemory(data, header->num_bytes)) { 52 ReportValidationError(validation_context, 53 VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); 54 return false; 55 } 56 57 return true; 58 } 59 60 bool ValidateNonInlinedUnionHeaderAndClaimMemory( 61 const void* data, 62 ValidationContext* validation_context) { 63 if (!IsAligned(data)) { 64 ReportValidationError(validation_context, 65 VALIDATION_ERROR_MISALIGNED_OBJECT); 66 return false; 67 } 68 69 if (!validation_context->ClaimMemory(data, kUnionDataSize) || 70 *static_cast<const uint32_t*>(data) != kUnionDataSize) { 71 ReportValidationError(validation_context, 72 VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); 73 return false; 74 } 75 76 return true; 77 } 78 79 bool ValidateMessageIsRequestWithoutResponse( 80 const Message* message, 81 ValidationContext* validation_context) { 82 if (message->has_flag(Message::kFlagIsResponse) || 83 message->has_flag(Message::kFlagExpectsResponse)) { 84 ReportValidationError(validation_context, 85 VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); 86 return false; 87 } 88 return true; 89 } 90 91 bool ValidateMessageIsRequestExpectingResponse( 92 const Message* message, 93 ValidationContext* validation_context) { 94 if (message->has_flag(Message::kFlagIsResponse) || 95 !message->has_flag(Message::kFlagExpectsResponse)) { 96 ReportValidationError(validation_context, 97 VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); 98 return false; 99 } 100 return true; 101 } 102 103 bool ValidateMessageIsResponse(const Message* message, 104 ValidationContext* validation_context) { 105 if (message->has_flag(Message::kFlagExpectsResponse) || 106 !message->has_flag(Message::kFlagIsResponse)) { 107 ReportValidationError(validation_context, 108 VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); 109 return false; 110 } 111 return true; 112 } 113 114 bool IsHandleOrInterfaceValid(const AssociatedInterface_Data& input) { 115 return input.handle.is_valid(); 116 } 117 118 bool IsHandleOrInterfaceValid(const AssociatedEndpointHandle_Data& input) { 119 return input.is_valid(); 120 } 121 122 bool IsHandleOrInterfaceValid(const Interface_Data& input) { 123 return input.handle.is_valid(); 124 } 125 126 bool IsHandleOrInterfaceValid(const Handle_Data& input) { 127 return input.is_valid(); 128 } 129 130 bool ValidateHandleOrInterfaceNonNullable( 131 const AssociatedInterface_Data& input, 132 int field_index, 133 ValidationContext* validation_context) { 134 if (IsHandleOrInterfaceValid(input)) 135 return true; 136 137 ReportNonNullableValidationError( 138 validation_context, VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID, 139 field_index); 140 return false; 141 } 142 143 bool ValidateHandleOrInterfaceNonNullable( 144 const AssociatedEndpointHandle_Data& input, 145 int field_index, 146 ValidationContext* validation_context) { 147 if (IsHandleOrInterfaceValid(input)) 148 return true; 149 150 ReportNonNullableValidationError( 151 validation_context, VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID, 152 field_index); 153 return false; 154 } 155 156 bool ValidateHandleOrInterfaceNonNullable( 157 const Interface_Data& input, 158 int field_index, 159 ValidationContext* validation_context) { 160 if (IsHandleOrInterfaceValid(input)) 161 return true; 162 163 ReportNonNullableValidationError(validation_context, 164 VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, 165 field_index); 166 return false; 167 } 168 169 bool ValidateHandleOrInterfaceNonNullable( 170 const Handle_Data& input, 171 int field_index, 172 ValidationContext* validation_context) { 173 if (IsHandleOrInterfaceValid(input)) 174 return true; 175 176 ReportNonNullableValidationError(validation_context, 177 VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, 178 field_index); 179 return false; 180 } 181 182 bool ValidateHandleOrInterface(const AssociatedInterface_Data& input, 183 ValidationContext* validation_context) { 184 if (validation_context->ClaimAssociatedEndpointHandle(input.handle)) 185 return true; 186 187 ReportValidationError(validation_context, 188 VALIDATION_ERROR_ILLEGAL_INTERFACE_ID); 189 return false; 190 } 191 192 bool ValidateHandleOrInterface(const AssociatedEndpointHandle_Data& input, 193 ValidationContext* validation_context) { 194 if (validation_context->ClaimAssociatedEndpointHandle(input)) 195 return true; 196 197 ReportValidationError(validation_context, 198 VALIDATION_ERROR_ILLEGAL_INTERFACE_ID); 199 return false; 200 } 201 202 bool ValidateHandleOrInterface(const Interface_Data& input, 203 ValidationContext* validation_context) { 204 if (validation_context->ClaimHandle(input.handle)) 205 return true; 206 207 ReportValidationError(validation_context, VALIDATION_ERROR_ILLEGAL_HANDLE); 208 return false; 209 } 210 211 bool ValidateHandleOrInterface(const Handle_Data& input, 212 ValidationContext* validation_context) { 213 if (validation_context->ClaimHandle(input)) 214 return true; 215 216 ReportValidationError(validation_context, VALIDATION_ERROR_ILLEGAL_HANDLE); 217 return false; 218 } 219 220 } // namespace internal 221 } // namespace mojo 222