Index: mojo/public/cpp/bindings/lib/message_header_validator.cc |
diff --git a/mojo/public/cpp/bindings/lib/message_header_validator.cc b/mojo/public/cpp/bindings/lib/message_header_validator.cc |
index 1396fd1ab715dc3c685b8fe7773cf7083ebc0945..d91359870366d310eb304aef51f38a3581627df9 100644 |
--- a/mojo/public/cpp/bindings/lib/message_header_validator.cc |
+++ b/mojo/public/cpp/bindings/lib/message_header_validator.cc |
@@ -5,49 +5,52 @@ |
#include "mojo/public/cpp/bindings/lib/message_header_validator.h" |
#include "mojo/public/cpp/bindings/lib/bindings_serialization.h" |
+#include "mojo/public/cpp/bindings/lib/bounds_checker.h" |
+#include "mojo/public/cpp/bindings/lib/validation_errors.h" |
namespace mojo { |
namespace internal { |
namespace { |
-bool IsValidMessageHeader(const internal::MessageHeader* header) { |
+bool IsValidMessageHeader(const MessageHeader* header) { |
// NOTE: Our goal is to preserve support for future extension of the message |
// header. If we encounter fields we do not understand, we must ignore them. |
- // Validate num_bytes: |
- |
- if (header->num_bytes < sizeof(internal::MessageHeader)) |
- return false; |
- if (internal::Align(header->num_bytes) != header->num_bytes) |
- return false; |
- |
- // Validate num_fields: |
- |
- if (header->num_fields < 2) |
- return false; |
+ // Extra validation of the struct header: |
if (header->num_fields == 2) { |
- if (header->num_bytes != sizeof(internal::MessageHeader)) |
+ if (header->num_bytes != sizeof(MessageHeader)) { |
+ ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); |
return false; |
+ } |
} else if (header->num_fields == 3) { |
- if (header->num_bytes != sizeof(internal::MessageHeaderWithRequestID)) |
+ if (header->num_bytes != sizeof(MessageHeaderWithRequestID)) { |
+ ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); |
return false; |
+ } |
} else if (header->num_fields > 3) { |
- if (header->num_bytes < sizeof(internal::MessageHeaderWithRequestID)) |
+ if (header->num_bytes < sizeof(MessageHeaderWithRequestID)) { |
+ ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); |
return false; |
+ } |
} |
// Validate flags (allow unknown bits): |
// These flags require a RequestID. |
if (header->num_fields < 3 && |
- ((header->flags & internal::kMessageExpectsResponse) || |
- (header->flags & internal::kMessageIsResponse))) |
+ ((header->flags & kMessageExpectsResponse) || |
+ (header->flags & kMessageIsResponse))) { |
+ ReportValidationError(VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID); |
return false; |
+ } |
// These flags are mutually exclusive. |
- if ((header->flags & internal::kMessageExpectsResponse) && |
- (header->flags & internal::kMessageIsResponse)) |
+ if ((header->flags & kMessageExpectsResponse) && |
+ (header->flags & kMessageIsResponse)) { |
+ ReportValidationError( |
+ VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINAION); |
return false; |
+ } |
return true; |
} |
@@ -59,9 +62,12 @@ MessageHeaderValidator::MessageHeaderValidator(MessageReceiver* sink) |
} |
bool MessageHeaderValidator::Accept(Message* message) { |
- // Make sure the message header isn't truncated before we start to read it. |
- if (message->data_num_bytes() < sizeof(internal::MessageHeader) || |
- message->data_num_bytes() < message->header()->num_bytes) { |
+ // Pass 0 as number of handles because we don't expect any in the header, even |
+ // if |message| contains handles. |
+ BoundsChecker bounds_checker(message->data(), message->data_num_bytes(), 0); |
+ |
+ if (!ValidateStructHeader(message->data(), sizeof(MessageHeader), 2, |
+ &bounds_checker)) { |
return false; |
} |