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/lib/bindings_internal.h"
11 #include "mojo/public/cpp/bindings/lib/serialization_util.h"
12 #include "mojo/public/cpp/bindings/lib/validate_params.h"
13 #include "mojo/public/cpp/bindings/lib/validation_context.h"
14 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
15 #include "mojo/public/cpp/bindings/message.h"
16
17 namespace mojo {
18 namespace internal {
19
20 // Checks whether decoding the pointer will overflow and produce a pointer
21 // smaller than |offset|.
22 bool ValidateEncodedPointer(const uint64_t* offset);
23
24 template <typename T>
ValidatePointer(const Pointer<T> & input,ValidationContext * validation_context)25 bool ValidatePointer(const Pointer<T>& input,
26 ValidationContext* validation_context) {
27 bool result = ValidateEncodedPointer(&input.offset);
28 if (!result)
29 ReportValidationError(validation_context, VALIDATION_ERROR_ILLEGAL_POINTER);
30
31 return result;
32 }
33
34 // Validates that |data| contains a valid struct header, in terms of alignment
35 // and size (i.e., the |num_bytes| field of the header is sufficient for storing
36 // the header itself). Besides, it checks that the memory range
37 // [data, data + num_bytes) is not marked as occupied by other objects in
38 // |validation_context|. On success, the memory range is marked as occupied.
39 // Note: Does not verify |version| or that |num_bytes| is correct for the
40 // claimed version.
41 bool ValidateStructHeaderAndClaimMemory(const void* data,
42 ValidationContext* validation_context);
43
44 // Validates that |data| contains a valid union header, in terms of alignment
45 // and size. If not inlined, 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 bool ValidateUnionHeaderAndClaimMemory(const void* data,
49 bool inlined,
50 ValidationContext* validation_context);
51
52 // Validates that the message is a request which doesn't expect a response.
53 bool ValidateMessageIsRequestWithoutResponse(
54 const Message* message,
55 ValidationContext* validation_context);
56
57 // Validates that the message is a request expecting a response.
58 bool ValidateMessageIsRequestExpectingResponse(
59 const Message* message,
60 ValidationContext* validation_context);
61
62 // Validates that the message is a response.
63 bool ValidateMessageIsResponse(const Message* message,
64 ValidationContext* validation_context);
65
66 // Validates that the message payload is a valid struct of type ParamsType.
67 template <typename ParamsType>
ValidateMessagePayload(const Message * message,ValidationContext * validation_context)68 bool ValidateMessagePayload(const Message* message,
69 ValidationContext* validation_context) {
70 return ParamsType::Validate(message->payload(), validation_context);
71 }
72
73 // The following methods validate control messages defined in
74 // interface_control_messages.mojom.
75 bool ValidateControlRequest(const Message* message,
76 ValidationContext* validation_context);
77 bool ValidateControlResponse(const Message* message,
78 ValidationContext* validation_context);
79
80 // The following Validate.*NonNullable() functions validate that the given
81 // |input| is not null/invalid.
82 template <typename T>
ValidatePointerNonNullable(const T & input,const char * error_message,ValidationContext * validation_context)83 bool ValidatePointerNonNullable(const T& input,
84 const char* error_message,
85 ValidationContext* validation_context) {
86 if (input.offset)
87 return true;
88
89 ReportValidationError(validation_context,
90 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
91 error_message);
92 return false;
93 }
94
95 template <typename T>
ValidateInlinedUnionNonNullable(const T & input,const char * error_message,ValidationContext * validation_context)96 bool ValidateInlinedUnionNonNullable(const T& input,
97 const char* error_message,
98 ValidationContext* validation_context) {
99 if (!input.is_null())
100 return true;
101
102 ReportValidationError(validation_context,
103 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
104 error_message);
105 return false;
106 }
107
108 bool IsHandleOrInterfaceValid(const AssociatedInterface_Data& input);
109 bool IsHandleOrInterfaceValid(const AssociatedInterfaceRequest_Data& input);
110 bool IsHandleOrInterfaceValid(const Interface_Data& input);
111 bool IsHandleOrInterfaceValid(const Handle_Data& input);
112
113 bool ValidateHandleOrInterfaceNonNullable(
114 const AssociatedInterface_Data& input,
115 const char* error_message,
116 ValidationContext* validation_context);
117 bool ValidateHandleOrInterfaceNonNullable(
118 const AssociatedInterfaceRequest_Data& input,
119 const char* error_message,
120 ValidationContext* validation_context);
121 bool ValidateHandleOrInterfaceNonNullable(
122 const Interface_Data& input,
123 const char* error_message,
124 ValidationContext* validation_context);
125 bool ValidateHandleOrInterfaceNonNullable(
126 const Handle_Data& input,
127 const char* error_message,
128 ValidationContext* validation_context);
129
130 template <typename T>
ValidateContainer(const Pointer<T> & input,ValidationContext * validation_context,const ContainerValidateParams * validate_params)131 bool ValidateContainer(const Pointer<T>& input,
132 ValidationContext* validation_context,
133 const ContainerValidateParams* validate_params) {
134 return ValidatePointer(input, validation_context) &&
135 T::Validate(input.Get(), validation_context, validate_params);
136 }
137
138 template <typename T>
ValidateStruct(const Pointer<T> & input,ValidationContext * validation_context)139 bool ValidateStruct(const Pointer<T>& input,
140 ValidationContext* validation_context) {
141 return ValidatePointer(input, validation_context) &&
142 T::Validate(input.Get(), validation_context);
143 }
144
145 template <typename T>
ValidateInlinedUnion(const T & input,ValidationContext * validation_context)146 bool ValidateInlinedUnion(const T& input,
147 ValidationContext* validation_context) {
148 return T::Validate(&input, validation_context, true);
149 }
150
151 template <typename T>
ValidateNonInlinedUnion(const Pointer<T> & input,ValidationContext * validation_context)152 bool ValidateNonInlinedUnion(const Pointer<T>& input,
153 ValidationContext* validation_context) {
154 return ValidatePointer(input, validation_context) &&
155 T::Validate(input.Get(), validation_context, false);
156 }
157
158 bool ValidateHandleOrInterface(const AssociatedInterface_Data& input,
159 ValidationContext* validation_context);
160 bool ValidateHandleOrInterface(const AssociatedInterfaceRequest_Data& input,
161 ValidationContext* validation_context);
162 bool ValidateHandleOrInterface(const Interface_Data& input,
163 ValidationContext* validation_context);
164 bool ValidateHandleOrInterface(const Handle_Data& input,
165 ValidationContext* validation_context);
166
167 } // namespace internal
168 } // namespace mojo
169
170 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_UTIL_H_
171