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