• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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|.
ValidateEncodedPointer(const uint64_t * 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>
ValidatePointer(const Pointer<T> & input,ValidationContext * validation_context)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>
ValidateMessagePayload(const Message * message,ValidationContext * validation_context)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>
ValidatePointerNonNullable(const T & input,int field_index,ValidationContext * validation_context)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>
ValidateInlinedUnionNonNullable(const T & input,int field_index,ValidationContext * validation_context)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>
ValidateContainer(const Pointer<T> & input,ValidationContext * validation_context,const ContainerValidateParams * validate_params)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>
ValidateStruct(const Pointer<T> & input,ValidationContext * validation_context)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>
ValidateInlinedUnion(const T & input,ValidationContext * validation_context)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>
ValidateNonInlinedUnion(const Pointer<T> & input,ValidationContext * validation_context)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