OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/public/cpp/bindings/lib/message_header_validator.h" | 5 #include "mojo/public/cpp/bindings/lib/message_header_validator.h" |
6 | 6 |
7 #include "mojo/public/cpp/bindings/lib/bindings_serialization.h" | 7 #include "mojo/public/cpp/bindings/lib/bindings_serialization.h" |
| 8 #include "mojo/public/cpp/bindings/lib/bounds_checker.h" |
| 9 #include "mojo/public/cpp/bindings/lib/validation_errors.h" |
8 | 10 |
9 namespace mojo { | 11 namespace mojo { |
10 namespace internal { | 12 namespace internal { |
11 namespace { | 13 namespace { |
12 | 14 |
13 bool IsValidMessageHeader(const internal::MessageHeader* header) { | 15 bool IsValidMessageHeader(const MessageHeader* header) { |
14 // NOTE: Our goal is to preserve support for future extension of the message | 16 // NOTE: Our goal is to preserve support for future extension of the message |
15 // header. If we encounter fields we do not understand, we must ignore them. | 17 // header. If we encounter fields we do not understand, we must ignore them. |
16 | 18 |
17 // Validate num_bytes: | 19 // Extra validation of the struct header: |
18 | |
19 if (header->num_bytes < sizeof(internal::MessageHeader)) | |
20 return false; | |
21 if (internal::Align(header->num_bytes) != header->num_bytes) | |
22 return false; | |
23 | |
24 // Validate num_fields: | |
25 | |
26 if (header->num_fields < 2) | |
27 return false; | |
28 if (header->num_fields == 2) { | 20 if (header->num_fields == 2) { |
29 if (header->num_bytes != sizeof(internal::MessageHeader)) | 21 if (header->num_bytes != sizeof(MessageHeader)) { |
| 22 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); |
30 return false; | 23 return false; |
| 24 } |
31 } else if (header->num_fields == 3) { | 25 } else if (header->num_fields == 3) { |
32 if (header->num_bytes != sizeof(internal::MessageHeaderWithRequestID)) | 26 if (header->num_bytes != sizeof(MessageHeaderWithRequestID)) { |
| 27 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); |
33 return false; | 28 return false; |
| 29 } |
34 } else if (header->num_fields > 3) { | 30 } else if (header->num_fields > 3) { |
35 if (header->num_bytes < sizeof(internal::MessageHeaderWithRequestID)) | 31 if (header->num_bytes < sizeof(MessageHeaderWithRequestID)) { |
| 32 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); |
36 return false; | 33 return false; |
| 34 } |
37 } | 35 } |
38 | 36 |
39 // Validate flags (allow unknown bits): | 37 // Validate flags (allow unknown bits): |
40 | 38 |
41 // These flags require a RequestID. | 39 // These flags require a RequestID. |
42 if (header->num_fields < 3 && | 40 if (header->num_fields < 3 && |
43 ((header->flags & internal::kMessageExpectsResponse) || | 41 ((header->flags & kMessageExpectsResponse) || |
44 (header->flags & internal::kMessageIsResponse))) | 42 (header->flags & kMessageIsResponse))) { |
| 43 ReportValidationError(VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID); |
45 return false; | 44 return false; |
| 45 } |
46 | 46 |
47 // These flags are mutually exclusive. | 47 // These flags are mutually exclusive. |
48 if ((header->flags & internal::kMessageExpectsResponse) && | 48 if ((header->flags & kMessageExpectsResponse) && |
49 (header->flags & internal::kMessageIsResponse)) | 49 (header->flags & kMessageIsResponse)) { |
| 50 ReportValidationError( |
| 51 VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINAION); |
50 return false; | 52 return false; |
| 53 } |
51 | 54 |
52 return true; | 55 return true; |
53 } | 56 } |
54 | 57 |
55 } // namespace | 58 } // namespace |
56 | 59 |
57 MessageHeaderValidator::MessageHeaderValidator(MessageReceiver* sink) | 60 MessageHeaderValidator::MessageHeaderValidator(MessageReceiver* sink) |
58 : MessageFilter(sink) { | 61 : MessageFilter(sink) { |
59 } | 62 } |
60 | 63 |
61 bool MessageHeaderValidator::Accept(Message* message) { | 64 bool MessageHeaderValidator::Accept(Message* message) { |
62 // Make sure the message header isn't truncated before we start to read it. | 65 // Pass 0 as number of handles because we don't expect any in the header, even |
63 if (message->data_num_bytes() < sizeof(internal::MessageHeader) || | 66 // if |message| contains handles. |
64 message->data_num_bytes() < message->header()->num_bytes) { | 67 BoundsChecker bounds_checker(message->data(), message->data_num_bytes(), 0); |
| 68 |
| 69 if (!ValidateStructHeader(message->data(), sizeof(MessageHeader), 2, |
| 70 &bounds_checker)) { |
65 return false; | 71 return false; |
66 } | 72 } |
67 | 73 |
68 if (!IsValidMessageHeader(message->header())) | 74 if (!IsValidMessageHeader(message->header())) |
69 return false; | 75 return false; |
70 | 76 |
71 return sink_->Accept(message); | 77 return sink_->Accept(message); |
72 } | 78 } |
73 | 79 |
74 } // namespace internal | 80 } // namespace internal |
75 } // namespace mojo | 81 } // namespace mojo |
OLD | NEW |