1// Copyright 2014 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/message_header_validator.h" 6 7#include "mojo/public/cpp/bindings/lib/validation_context.h" 8#include "mojo/public/cpp/bindings/lib/validation_errors.h" 9#include "mojo/public/cpp/bindings/lib/validation_util.h" 10 11namespace mojo { 12namespace { 13 14bool IsValidMessageHeader(const internal::MessageHeader* header, 15 internal::ValidationContext* validation_context) { 16 // NOTE: Our goal is to preserve support for future extension of the message 17 // header. If we encounter fields we do not understand, we must ignore them. 18 19 // Extra validation of the struct header: 20 if (header->version == 0) { 21 if (header->num_bytes != sizeof(internal::MessageHeader)) { 22 internal::ReportValidationError( 23 validation_context, 24 internal::VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); 25 return false; 26 } 27 } else if (header->version == 1) { 28 if (header->num_bytes != sizeof(internal::MessageHeaderWithRequestID)) { 29 internal::ReportValidationError( 30 validation_context, 31 internal::VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); 32 return false; 33 } 34 } else if (header->version > 1) { 35 if (header->num_bytes < sizeof(internal::MessageHeaderWithRequestID)) { 36 internal::ReportValidationError( 37 validation_context, 38 internal::VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); 39 return false; 40 } 41 } 42 43 // Validate flags (allow unknown bits): 44 45 // These flags require a RequestID. 46 if (header->version < 1 && ((header->flags & Message::kFlagExpectsResponse) || 47 (header->flags & Message::kFlagIsResponse))) { 48 internal::ReportValidationError( 49 validation_context, 50 internal::VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID); 51 return false; 52 } 53 54 // These flags are mutually exclusive. 55 if ((header->flags & Message::kFlagExpectsResponse) && 56 (header->flags & Message::kFlagIsResponse)) { 57 internal::ReportValidationError( 58 validation_context, 59 internal::VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); 60 return false; 61 } 62 63 return true; 64} 65 66} // namespace 67 68MessageHeaderValidator::MessageHeaderValidator(MessageReceiver* sink) 69 : MessageHeaderValidator("MessageHeaderValidator", sink) {} 70 71MessageHeaderValidator::MessageHeaderValidator(const std::string& description, 72 MessageReceiver* sink) 73 : MessageFilter(sink), description_(description) { 74} 75 76void MessageHeaderValidator::SetDescription(const std::string& description) { 77 description_ = description; 78} 79 80bool MessageHeaderValidator::Accept(Message* message) { 81 // Pass 0 as number of handles because we don't expect any in the header, even 82 // if |message| contains handles. 83 internal::ValidationContext validation_context( 84 message->data(), message->data_num_bytes(), 0, message, description_); 85 86 if (!internal::ValidateStructHeaderAndClaimMemory(message->data(), 87 &validation_context)) 88 return false; 89 90 if (!IsValidMessageHeader(message->header(), &validation_context)) 91 return false; 92 93 return sink_->Accept(message); 94} 95 96} // namespace mojo 97