• 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 "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|.
ValidateEncodedPointer(const uint64_t * 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>
ValidatePointer(const Pointer<T> & input,ValidationContext * validation_context)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>
ValidateMessagePayload(const Message * message,ValidationContext * validation_context)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>
ValidatePointerNonNullable(const T & input,const char * error_message,ValidationContext * validation_context)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>
ValidateInlinedUnionNonNullable(const T & input,const char * error_message,ValidationContext * validation_context)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>
ValidateContainer(const Pointer<T> & input,ValidationContext * validation_context,const ContainerValidateParams * validate_params)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>
ValidateStruct(const Pointer<T> & input,ValidationContext * validation_context)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>
ValidateInlinedUnion(const T & input,ValidationContext * validation_context)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>
ValidateNonInlinedUnion(const Pointer<T> & input,ValidationContext * validation_context)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