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
11 namespace mojo {
12 namespace {
13
IsValidMessageHeader(const internal::MessageHeader * header,internal::ValidationContext * validation_context)14 bool 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
MessageHeaderValidator(MessageReceiver * sink)68 MessageHeaderValidator::MessageHeaderValidator(MessageReceiver* sink)
69 : MessageHeaderValidator("MessageHeaderValidator", sink) {}
70
MessageHeaderValidator(const std::string & description,MessageReceiver * sink)71 MessageHeaderValidator::MessageHeaderValidator(const std::string& description,
72 MessageReceiver* sink)
73 : MessageFilter(sink), description_(description) {
74 }
75
SetDescription(const std::string & description)76 void MessageHeaderValidator::SetDescription(const std::string& description) {
77 description_ = description;
78 }
79
Accept(Message * message)80 bool 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