Home | History | Annotate | Download | only in lib
      1 // Copyright 2015 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 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_UTIL_H_
      6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_UTIL_H_
      7 
      8 #include <stdint.h>
      9 
     10 #include "mojo/public/cpp/bindings/bindings_export.h"
     11 #include "mojo/public/cpp/bindings/lib/bindings_internal.h"
     12 #include "mojo/public/cpp/bindings/lib/serialization_util.h"
     13 #include "mojo/public/cpp/bindings/lib/validate_params.h"
     14 #include "mojo/public/cpp/bindings/lib/validation_context.h"
     15 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
     16 #include "mojo/public/cpp/bindings/message.h"
     17 
     18 namespace mojo {
     19 namespace internal {
     20 
     21 // Checks whether decoding the pointer will overflow and produce a pointer
     22 // smaller than |offset|.
     23 inline bool ValidateEncodedPointer(const uint64_t* offset) {
     24   // - Make sure |*offset| is no more than 32-bits.
     25   // - Cast |offset| to uintptr_t so overflow behavior is well defined across
     26   //   32-bit and 64-bit systems.
     27   return *offset <= std::numeric_limits<uint32_t>::max() &&
     28          (reinterpret_cast<uintptr_t>(offset) +
     29               static_cast<uint32_t>(*offset) >=
     30           reinterpret_cast<uintptr_t>(offset));
     31 }
     32 
     33 template <typename T>
     34 bool ValidatePointer(const Pointer<T>& input,
     35                      ValidationContext* validation_context) {
     36   bool result = ValidateEncodedPointer(&input.offset);
     37   if (!result)
     38     ReportValidationError(validation_context, VALIDATION_ERROR_ILLEGAL_POINTER);
     39 
     40   return result;
     41 }
     42 
     43 // Validates that |data| contains a valid struct header, in terms of alignment
     44 // and size (i.e., the |num_bytes| field of the header is sufficient for storing
     45 // the header itself). Besides, it checks that the memory range
     46 // [data, data + num_bytes) is not marked as occupied by other objects in
     47 // |validation_context|. On success, the memory range is marked as occupied.
     48 // Note: Does not verify |version| or that |num_bytes| is correct for the
     49 // claimed version.
     50 MOJO_CPP_BINDINGS_EXPORT bool ValidateStructHeaderAndClaimMemory(
     51     const void* data,
     52     ValidationContext* validation_context);
     53 
     54 // Validates that |data| contains a valid union header, in terms of alignment
     55 // and size. It checks that the memory range [data, data + kUnionDataSize) is
     56 // not marked as occupied by other objects in |validation_context|. On success,
     57 // the memory range is marked as occupied.
     58 MOJO_CPP_BINDINGS_EXPORT bool ValidateNonInlinedUnionHeaderAndClaimMemory(
     59     const void* data,
     60     ValidationContext* validation_context);
     61 
     62 // Validates that the message is a request which doesn't expect a response.
     63 MOJO_CPP_BINDINGS_EXPORT bool ValidateMessageIsRequestWithoutResponse(
     64     const Message* message,
     65     ValidationContext* validation_context);
     66 
     67 // Validates that the message is a request expecting a response.
     68 MOJO_CPP_BINDINGS_EXPORT bool ValidateMessageIsRequestExpectingResponse(
     69     const Message* message,
     70     ValidationContext* validation_context);
     71 
     72 // Validates that the message is a response.
     73 MOJO_CPP_BINDINGS_EXPORT bool ValidateMessageIsResponse(
     74     const Message* message,
     75     ValidationContext* validation_context);
     76 
     77 // Validates that the message payload is a valid struct of type ParamsType.
     78 template <typename ParamsType>
     79 bool ValidateMessagePayload(const Message* message,
     80                             ValidationContext* validation_context) {
     81   return ParamsType::Validate(message->payload(), validation_context);
     82 }
     83 
     84 // The following Validate.*NonNullable() functions validate that the given
     85 // |input| is not null/invalid.
     86 template <typename T>
     87 bool ValidatePointerNonNullable(const T& input,
     88                                 const char* error_message,
     89                                 ValidationContext* validation_context) {
     90   if (input.offset)
     91     return true;
     92 
     93   ReportValidationError(validation_context,
     94                         VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
     95                         error_message);
     96   return false;
     97 }
     98 
     99 template <typename T>
    100 bool ValidateInlinedUnionNonNullable(const T& input,
    101                                      const char* error_message,
    102                                      ValidationContext* validation_context) {
    103   if (!input.is_null())
    104     return true;
    105 
    106   ReportValidationError(validation_context,
    107                         VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
    108                         error_message);
    109   return false;
    110 }
    111 
    112 MOJO_CPP_BINDINGS_EXPORT bool IsHandleOrInterfaceValid(
    113     const AssociatedInterface_Data& input);
    114 MOJO_CPP_BINDINGS_EXPORT bool IsHandleOrInterfaceValid(
    115     const AssociatedEndpointHandle_Data& input);
    116 MOJO_CPP_BINDINGS_EXPORT bool IsHandleOrInterfaceValid(
    117     const Interface_Data& input);
    118 MOJO_CPP_BINDINGS_EXPORT bool IsHandleOrInterfaceValid(
    119     const Handle_Data& input);
    120 
    121 MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterfaceNonNullable(
    122     const AssociatedInterface_Data& input,
    123     const char* error_message,
    124     ValidationContext* validation_context);
    125 MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterfaceNonNullable(
    126     const AssociatedEndpointHandle_Data& input,
    127     const char* error_message,
    128     ValidationContext* validation_context);
    129 MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterfaceNonNullable(
    130     const Interface_Data& input,
    131     const char* error_message,
    132     ValidationContext* validation_context);
    133 MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterfaceNonNullable(
    134     const Handle_Data& input,
    135     const char* error_message,
    136     ValidationContext* validation_context);
    137 
    138 template <typename T>
    139 bool ValidateContainer(const Pointer<T>& input,
    140                        ValidationContext* validation_context,
    141                        const ContainerValidateParams* validate_params) {
    142   ValidationContext::ScopedDepthTracker depth_tracker(validation_context);
    143   if (validation_context->ExceedsMaxDepth()) {
    144     ReportValidationError(validation_context,
    145                           VALIDATION_ERROR_MAX_RECURSION_DEPTH);
    146     return false;
    147   }
    148   return ValidatePointer(input, validation_context) &&
    149          T::Validate(input.Get(), validation_context, validate_params);
    150 }
    151 
    152 template <typename T>
    153 bool ValidateStruct(const Pointer<T>& input,
    154                     ValidationContext* validation_context) {
    155   ValidationContext::ScopedDepthTracker depth_tracker(validation_context);
    156   if (validation_context->ExceedsMaxDepth()) {
    157     ReportValidationError(validation_context,
    158                           VALIDATION_ERROR_MAX_RECURSION_DEPTH);
    159     return false;
    160   }
    161   return ValidatePointer(input, validation_context) &&
    162          T::Validate(input.Get(), validation_context);
    163 }
    164 
    165 template <typename T>
    166 bool ValidateInlinedUnion(const T& input,
    167                           ValidationContext* validation_context) {
    168   ValidationContext::ScopedDepthTracker depth_tracker(validation_context);
    169   if (validation_context->ExceedsMaxDepth()) {
    170     ReportValidationError(validation_context,
    171                           VALIDATION_ERROR_MAX_RECURSION_DEPTH);
    172     return false;
    173   }
    174   return T::Validate(&input, validation_context, true);
    175 }
    176 
    177 template <typename T>
    178 bool ValidateNonInlinedUnion(const Pointer<T>& input,
    179                              ValidationContext* validation_context) {
    180   ValidationContext::ScopedDepthTracker depth_tracker(validation_context);
    181   if (validation_context->ExceedsMaxDepth()) {
    182     ReportValidationError(validation_context,
    183                           VALIDATION_ERROR_MAX_RECURSION_DEPTH);
    184     return false;
    185   }
    186   return ValidatePointer(input, validation_context) &&
    187          T::Validate(input.Get(), validation_context, false);
    188 }
    189 
    190 MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterface(
    191     const AssociatedInterface_Data& input,
    192     ValidationContext* validation_context);
    193 MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterface(
    194     const AssociatedEndpointHandle_Data& input,
    195     ValidationContext* validation_context);
    196 MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterface(
    197     const Interface_Data& input,
    198     ValidationContext* validation_context);
    199 MOJO_CPP_BINDINGS_EXPORT bool ValidateHandleOrInterface(
    200     const Handle_Data& input,
    201     ValidationContext* validation_context);
    202 
    203 }  // namespace internal
    204 }  // namespace mojo
    205 
    206 #endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_UTIL_H_
    207