OLD | NEW |
| (Empty) |
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/lib/message_header_validator.h" | |
6 | |
7 #include <string> | |
8 | |
9 #include "mojo/public/cpp/bindings/lib/bounds_checker.h" | |
10 #include "mojo/public/cpp/bindings/lib/message_validation.h" | |
11 #include "mojo/public/cpp/bindings/lib/validation_errors.h" | |
12 #include "mojo/public/cpp/bindings/lib/validation_util.h" | |
13 #include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h" | |
14 | |
15 namespace mojo { | |
16 namespace internal { | |
17 namespace { | |
18 | |
19 ValidationError ValidateMessageHeader(const MessageHeader* header, | |
20 std::string* err) { | |
21 // NOTE: Our goal is to preserve support for future extension of the message | |
22 // header. If we encounter fields we do not understand, we must ignore them. | |
23 // Extra validation of the struct header: | |
24 if (header->version == 0) { | |
25 if (header->num_bytes != sizeof(MessageHeader)) { | |
26 MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) | |
27 << "message header size is incorrect"; | |
28 return ValidationError::UNEXPECTED_STRUCT_HEADER; | |
29 } | |
30 } else if (header->version == 1) { | |
31 if (header->num_bytes != sizeof(MessageHeaderWithRequestID)) { | |
32 MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) | |
33 << "message header (version = 1) size is incorrect"; | |
34 return ValidationError::UNEXPECTED_STRUCT_HEADER; | |
35 } | |
36 } else if (header->version > 1) { | |
37 if (header->num_bytes < sizeof(MessageHeaderWithRequestID)) { | |
38 MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) | |
39 << "message header (version > 1) size is too small"; | |
40 return ValidationError::UNEXPECTED_STRUCT_HEADER; | |
41 } | |
42 } | |
43 | |
44 // Validate flags (allow unknown bits): | |
45 | |
46 // These flags require a RequestID. | |
47 if (header->version < 1 && ((header->flags & kMessageExpectsResponse) || | |
48 (header->flags & kMessageIsResponse))) { | |
49 MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) | |
50 << "message header associates itself with a response but does not " | |
51 "contain a request id"; | |
52 return ValidationError::MESSAGE_HEADER_MISSING_REQUEST_ID; | |
53 } | |
54 | |
55 // These flags are mutually exclusive. | |
56 if ((header->flags & kMessageExpectsResponse) && | |
57 (header->flags & kMessageIsResponse)) { | |
58 MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) | |
59 << "message header cannot indicate itself as a response while also " | |
60 "expecting a response"; | |
61 return ValidationError::MESSAGE_HEADER_INVALID_FLAGS; | |
62 } | |
63 | |
64 return ValidationError::NONE; | |
65 } | |
66 | |
67 } // namespace | |
68 | |
69 ValidationError MessageHeaderValidator::Validate(const Message* message, | |
70 std::string* err) { | |
71 // Pass 0 as number of handles because we don't expect any in the header, even | |
72 // if |message| contains handles. | |
73 BoundsChecker bounds_checker(message->data(), message->data_num_bytes(), 0); | |
74 | |
75 ValidationError result = | |
76 ValidateStructHeaderAndClaimMemory(message->data(), &bounds_checker, err); | |
77 if (result != ValidationError::NONE) | |
78 return result; | |
79 | |
80 return ValidateMessageHeader(message->header(), err); | |
81 } | |
82 | |
83 ValidationError ValidateControlRequest(const Message* message, | |
84 std::string* err) { | |
85 ValidationError retval; | |
86 switch (message->header()->name) { | |
87 case kRunMessageId: { | |
88 retval = ValidateMessageIsRequestExpectingResponse(message, err); | |
89 if (retval != ValidationError::NONE) | |
90 return retval; | |
91 | |
92 return ValidateMessagePayload<RunMessageParams_Data>(message, err); | |
93 } | |
94 | |
95 case kRunOrClosePipeMessageId: { | |
96 retval = ValidateMessageIsRequestWithoutResponse(message, err); | |
97 if (retval != ValidationError::NONE) | |
98 return retval; | |
99 | |
100 return ValidateMessagePayload<RunOrClosePipeMessageParams_Data>(message, | |
101 err); | |
102 } | |
103 | |
104 default: { | |
105 MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) | |
106 << "unknown InterfaceControlMessage request message name: " | |
107 << message->header()->name; | |
108 return ValidationError::MESSAGE_HEADER_UNKNOWN_METHOD; | |
109 } | |
110 } | |
111 | |
112 return ValidationError::NONE; | |
113 } | |
114 | |
115 ValidationError ValidateControlResponse(const Message* message, | |
116 std::string* err) { | |
117 ValidationError retval = ValidateMessageIsResponse(message, err); | |
118 if (retval != ValidationError::NONE) | |
119 return retval; | |
120 | |
121 switch (message->header()->name) { | |
122 case kRunMessageId: | |
123 return ValidateMessagePayload<RunResponseMessageParams_Data>(message, | |
124 err); | |
125 } | |
126 | |
127 MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err) | |
128 << "unknown InterfaceControlMessage response message name: " | |
129 << message->header()->name; | |
130 return ValidationError::MESSAGE_HEADER_UNKNOWN_METHOD; | |
131 } | |
132 | |
133 } // namespace internal | |
134 } // namespace mojo | |
OLD | NEW |