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