• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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