// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "mojo/public/cpp/bindings/lib/validation_util.h" #include "mojo/public/cpp/bindings/lib/bindings_serialization.h" #include "mojo/public/cpp/bindings/lib/message_internal.h" #include "mojo/public/cpp/bindings/lib/validation_errors.h" #include "mojo/public/interfaces/bindings/interface_control_messages.mojom.h" namespace mojo { namespace internal { bool ValidateEncodedPointer(const uint64_t* offset) { // Cast to uintptr_t so overflow behavior is well defined. return reinterpret_cast(offset) + *offset >= reinterpret_cast(offset); } bool ValidateStructHeaderAndClaimMemory(const void* data, BoundsChecker* bounds_checker) { if (!IsAligned(data)) { ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT); return false; } if (!bounds_checker->IsValidRange(data, sizeof(StructHeader))) { ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); return false; } const StructHeader* header = static_cast(data); if (header->num_bytes < sizeof(StructHeader)) { ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); return false; } if (!bounds_checker->ClaimMemory(data, header->num_bytes)) { ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); return false; } return true; } bool ValidateMessageIsRequestWithoutResponse(const Message* message) { if (message->has_flag(kMessageIsResponse) || message->has_flag(kMessageExpectsResponse)) { ReportValidationError(VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); return false; } return true; } bool ValidateMessageIsRequestExpectingResponse(const Message* message) { if (message->has_flag(kMessageIsResponse) || !message->has_flag(kMessageExpectsResponse)) { ReportValidationError(VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); return false; } return true; } bool ValidateMessageIsResponse(const Message* message) { if (message->has_flag(kMessageExpectsResponse) || !message->has_flag(kMessageIsResponse)) { ReportValidationError(VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); return false; } return true; } bool ValidateControlRequest(const Message* message) { switch (message->header()->name) { case kRunMessageId: return ValidateMessageIsRequestExpectingResponse(message) && ValidateMessagePayload(message); case kRunOrClosePipeMessageId: return ValidateMessageIsRequestWithoutResponse(message) && ValidateMessagePayload(message); } return false; } bool ValidateControlResponse(const Message* message) { if (!ValidateMessageIsResponse(message)) return false; switch (message->header()->name) { case kRunMessageId: return ValidateMessagePayload(message); } return false; } } // namespace internal } // namespace mojo