Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: mojo/public/cpp/bindings/lib/array_internal.h

Issue 2064903002: Mojo: Report bindings validation errors via MojoNotifyBadMessage (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/public/cpp/bindings/BUILD.gn ('k') | mojo/public/cpp/bindings/lib/binding_state.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ 6 #define MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 #include <new> 10 #include <new>
11 #include <utility> 11 #include <utility>
12 #include <vector> 12 #include <vector>
13 13
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "mojo/public/c/system/macros.h" 15 #include "mojo/public/c/system/macros.h"
16 #include "mojo/public/cpp/bindings/lib/bindings_internal.h" 16 #include "mojo/public/cpp/bindings/lib/bindings_internal.h"
17 #include "mojo/public/cpp/bindings/lib/bounds_checker.h"
18 #include "mojo/public/cpp/bindings/lib/buffer.h" 17 #include "mojo/public/cpp/bindings/lib/buffer.h"
19 #include "mojo/public/cpp/bindings/lib/serialization_util.h" 18 #include "mojo/public/cpp/bindings/lib/serialization_util.h"
20 #include "mojo/public/cpp/bindings/lib/template_util.h" 19 #include "mojo/public/cpp/bindings/lib/template_util.h"
21 #include "mojo/public/cpp/bindings/lib/validate_params.h" 20 #include "mojo/public/cpp/bindings/lib/validate_params.h"
21 #include "mojo/public/cpp/bindings/lib/validation_context.h"
22 #include "mojo/public/cpp/bindings/lib/validation_errors.h" 22 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
23 #include "mojo/public/cpp/bindings/lib/validation_util.h" 23 #include "mojo/public/cpp/bindings/lib/validation_util.h"
24 24
25 namespace mojo { 25 namespace mojo {
26 namespace internal { 26 namespace internal {
27 27
28 // std::numeric_limits<uint32_t>::max() is not a compile-time constant (until 28 // std::numeric_limits<uint32_t>::max() is not a compile-time constant (until
29 // C++11). 29 // C++11).
30 const uint32_t kMaxUint32 = 0xFFFFFFFF; 30 const uint32_t kMaxUint32 = 0xFFFFFFFF;
31 31
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 typedef typename ArrayDataTraits<T>::StorageType ElementType; 139 typedef typename ArrayDataTraits<T>::StorageType ElementType;
140 140
141 static void EncodePointers(const ArrayHeader* header, 141 static void EncodePointers(const ArrayHeader* header,
142 ElementType* elements) {} 142 ElementType* elements) {}
143 143
144 static void DecodePointers(const ArrayHeader* header, 144 static void DecodePointers(const ArrayHeader* header,
145 ElementType* elements) {} 145 ElementType* elements) {}
146 146
147 static bool ValidateElements(const ArrayHeader* header, 147 static bool ValidateElements(const ArrayHeader* header,
148 const ElementType* elements, 148 const ElementType* elements,
149 BoundsChecker* bounds_checker, 149 ValidationContext* validation_context,
150 const ContainerValidateParams* validate_params) { 150 const ContainerValidateParams* validate_params) {
151 DCHECK(!validate_params->element_is_nullable) 151 DCHECK(!validate_params->element_is_nullable)
152 << "Primitive type should be non-nullable"; 152 << "Primitive type should be non-nullable";
153 DCHECK(!validate_params->element_validate_params) 153 DCHECK(!validate_params->element_validate_params)
154 << "Primitive type should not have array validate params"; 154 << "Primitive type should not have array validate params";
155 155
156 if (!validate_params->validate_enum_func) 156 if (!validate_params->validate_enum_func)
157 return true; 157 return true;
158 158
159 // Enum validation. 159 // Enum validation.
160 for (uint32_t i = 0; i < header->num_elements; ++i) { 160 for (uint32_t i = 0; i < header->num_elements; ++i) {
161 if (!validate_params->validate_enum_func(elements[i])) 161 if (!validate_params->validate_enum_func(elements[i], validation_context))
162 return false; 162 return false;
163 } 163 }
164 return true; 164 return true;
165 } 165 }
166 }; 166 };
167 167
168 template <> 168 template <>
169 struct ArraySerializationHelper<Handle_Data, false> { 169 struct ArraySerializationHelper<Handle_Data, false> {
170 typedef ArrayDataTraits<Handle_Data>::StorageType ElementType; 170 typedef ArrayDataTraits<Handle_Data>::StorageType ElementType;
171 171
172 static void EncodePointers(const ArrayHeader* header, 172 static void EncodePointers(const ArrayHeader* header,
173 ElementType* elements) {} 173 ElementType* elements) {}
174 174
175 static void DecodePointers(const ArrayHeader* header, 175 static void DecodePointers(const ArrayHeader* header,
176 ElementType* elements) {} 176 ElementType* elements) {}
177 177
178 static bool ValidateElements(const ArrayHeader* header, 178 static bool ValidateElements(const ArrayHeader* header,
179 const ElementType* elements, 179 const ElementType* elements,
180 BoundsChecker* bounds_checker, 180 ValidationContext* validation_context,
181 const ContainerValidateParams* validate_params) { 181 const ContainerValidateParams* validate_params) {
182 DCHECK(!validate_params->element_validate_params) 182 DCHECK(!validate_params->element_validate_params)
183 << "Handle type should not have array validate params"; 183 << "Handle type should not have array validate params";
184 184
185 for (uint32_t i = 0; i < header->num_elements; ++i) { 185 for (uint32_t i = 0; i < header->num_elements; ++i) {
186 if (!validate_params->element_is_nullable && !elements[i].is_valid()) { 186 if (!validate_params->element_is_nullable && !elements[i].is_valid()) {
187 ReportValidationError( 187 ReportValidationError(
188 validation_context,
188 VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, 189 VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
189 MakeMessageWithArrayIndex( 190 MakeMessageWithArrayIndex(
190 "invalid handle in array expecting valid handles", 191 "invalid handle in array expecting valid handles",
191 header->num_elements, 192 header->num_elements,
192 i).c_str()); 193 i).c_str());
193 return false; 194 return false;
194 } 195 }
195 if (!bounds_checker->ClaimHandle(elements[i])) { 196 if (!validation_context->ClaimHandle(elements[i])) {
196 ReportValidationError(VALIDATION_ERROR_ILLEGAL_HANDLE); 197 ReportValidationError(validation_context,
198 VALIDATION_ERROR_ILLEGAL_HANDLE);
197 return false; 199 return false;
198 } 200 }
199 } 201 }
200 return true; 202 return true;
201 } 203 }
202 }; 204 };
203 205
204 template <typename P> 206 template <typename P>
205 struct ArraySerializationHelper<P*, false> { 207 struct ArraySerializationHelper<P*, false> {
206 typedef typename ArrayDataTraits<P*>::StorageType ElementType; 208 typedef typename ArrayDataTraits<P*>::StorageType ElementType;
207 209
208 static void EncodePointers(const ArrayHeader* header, ElementType* elements) { 210 static void EncodePointers(const ArrayHeader* header, ElementType* elements) {
209 for (uint32_t i = 0; i < header->num_elements; ++i) 211 for (uint32_t i = 0; i < header->num_elements; ++i)
210 Encode(&elements[i]); 212 Encode(&elements[i]);
211 } 213 }
212 214
213 static void DecodePointers(const ArrayHeader* header, ElementType* elements) { 215 static void DecodePointers(const ArrayHeader* header, ElementType* elements) {
214 for (uint32_t i = 0; i < header->num_elements; ++i) 216 for (uint32_t i = 0; i < header->num_elements; ++i)
215 Decode(&elements[i]); 217 Decode(&elements[i]);
216 } 218 }
217 219
218 static bool ValidateElements(const ArrayHeader* header, 220 static bool ValidateElements(const ArrayHeader* header,
219 const ElementType* elements, 221 const ElementType* elements,
220 BoundsChecker* bounds_checker, 222 ValidationContext* validation_context,
221 const ContainerValidateParams* validate_params) { 223 const ContainerValidateParams* validate_params) {
222 for (uint32_t i = 0; i < header->num_elements; ++i) { 224 for (uint32_t i = 0; i < header->num_elements; ++i) {
223 if (!validate_params->element_is_nullable && !elements[i].offset) { 225 if (!validate_params->element_is_nullable && !elements[i].offset) {
224 ReportValidationError( 226 ReportValidationError(
227 validation_context,
225 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, 228 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
226 MakeMessageWithArrayIndex("null in array expecting valid pointers", 229 MakeMessageWithArrayIndex("null in array expecting valid pointers",
227 header->num_elements, 230 header->num_elements,
228 i).c_str()); 231 i).c_str());
229 return false; 232 return false;
230 } 233 }
231 if (!ValidateEncodedPointer(&elements[i].offset)) { 234 if (!ValidateEncodedPointer(&elements[i].offset)) {
232 ReportValidationError(VALIDATION_ERROR_ILLEGAL_POINTER); 235 ReportValidationError(validation_context,
236 VALIDATION_ERROR_ILLEGAL_POINTER);
233 return false; 237 return false;
234 } 238 }
235 if (!ValidateCaller<P>::Run(DecodePointerRaw(&elements[i].offset), 239 if (!ValidateCaller<P>::Run(DecodePointerRaw(&elements[i].offset),
236 bounds_checker, 240 validation_context,
237 validate_params->element_validate_params)) { 241 validate_params->element_validate_params)) {
238 return false; 242 return false;
239 } 243 }
240 } 244 }
241 return true; 245 return true;
242 } 246 }
243 247
244 private: 248 private:
245 template <typename T> 249 template <typename T>
246 struct ValidateCaller { 250 struct ValidateCaller {
247 static bool Run(const void* data, 251 static bool Run(const void* data,
248 BoundsChecker* bounds_checker, 252 ValidationContext* validation_context,
249 const ContainerValidateParams* validate_params) { 253 const ContainerValidateParams* validate_params) {
250 DCHECK(!validate_params) 254 DCHECK(!validate_params)
251 << "Struct type should not have array validate params"; 255 << "Struct type should not have array validate params";
252 256
253 return T::Validate(data, bounds_checker); 257 return T::Validate(data, validation_context);
254 } 258 }
255 }; 259 };
256 260
257 template <typename Key, typename Value> 261 template <typename Key, typename Value>
258 struct ValidateCaller<Map_Data<Key, Value>> { 262 struct ValidateCaller<Map_Data<Key, Value>> {
259 static bool Run(const void* data, 263 static bool Run(const void* data,
260 BoundsChecker* bounds_checker, 264 ValidationContext* validation_context,
261 const ContainerValidateParams* validate_params) { 265 const ContainerValidateParams* validate_params) {
262 return Map_Data<Key, Value>::Validate(data, bounds_checker, 266 return Map_Data<Key, Value>::Validate(data, validation_context,
263 validate_params); 267 validate_params);
264 } 268 }
265 }; 269 };
266 270
267 template <typename T> 271 template <typename T>
268 struct ValidateCaller<Array_Data<T>> { 272 struct ValidateCaller<Array_Data<T>> {
269 static bool Run(const void* data, 273 static bool Run(const void* data,
270 BoundsChecker* bounds_checker, 274 ValidationContext* validation_context,
271 const ContainerValidateParams* validate_params) { 275 const ContainerValidateParams* validate_params) {
272 return Array_Data<T>::Validate(data, bounds_checker, validate_params); 276 return Array_Data<T>::Validate(data, validation_context, validate_params);
273 } 277 }
274 }; 278 };
275 }; 279 };
276 280
277 template <typename U> 281 template <typename U>
278 struct ArraySerializationHelper<U, true> { 282 struct ArraySerializationHelper<U, true> {
279 typedef typename ArrayDataTraits<U>::StorageType ElementType; 283 typedef typename ArrayDataTraits<U>::StorageType ElementType;
280 284
281 static void EncodePointers(const ArrayHeader* header, ElementType* elements) { 285 static void EncodePointers(const ArrayHeader* header, ElementType* elements) {
282 for (uint32_t i = 0; i < header->num_elements; ++i) 286 for (uint32_t i = 0; i < header->num_elements; ++i)
283 elements[i].EncodePointers(); 287 elements[i].EncodePointers();
284 } 288 }
285 289
286 static void DecodePointers(const ArrayHeader* header, ElementType* elements) { 290 static void DecodePointers(const ArrayHeader* header, ElementType* elements) {
287 for (uint32_t i = 0; i < header->num_elements; ++i) 291 for (uint32_t i = 0; i < header->num_elements; ++i)
288 elements[i].DecodePointers(); 292 elements[i].DecodePointers();
289 } 293 }
290 294
291 static bool ValidateElements(const ArrayHeader* header, 295 static bool ValidateElements(const ArrayHeader* header,
292 const ElementType* elements, 296 const ElementType* elements,
293 BoundsChecker* bounds_checker, 297 ValidationContext* validation_context,
294 const ContainerValidateParams* validate_params) { 298 const ContainerValidateParams* validate_params) {
295 for (uint32_t i = 0; i < header->num_elements; ++i) { 299 for (uint32_t i = 0; i < header->num_elements; ++i) {
296 if (!validate_params->element_is_nullable && elements[i].is_null()) { 300 if (!validate_params->element_is_nullable && elements[i].is_null()) {
297 ReportValidationError( 301 ReportValidationError(
302 validation_context,
298 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, 303 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
299 MakeMessageWithArrayIndex("null in array expecting valid unions", 304 MakeMessageWithArrayIndex("null in array expecting valid unions",
300 header->num_elements, i) 305 header->num_elements, i)
301 .c_str()); 306 .c_str());
302 return false; 307 return false;
303 } 308 }
304 if (!ElementType::Validate(elements + i, bounds_checker, true)) 309 if (!ElementType::Validate(elements + i, validation_context, true))
305 return false; 310 return false;
306 } 311 }
307 return true; 312 return true;
308 } 313 }
309 }; 314 };
310 315
311 template <typename T> 316 template <typename T>
312 class Array_Data { 317 class Array_Data {
313 public: 318 public:
314 using Traits = ArrayDataTraits<T>; 319 using Traits = ArrayDataTraits<T>;
315 using StorageType = typename Traits::StorageType; 320 using StorageType = typename Traits::StorageType;
316 using Ref = typename Traits::Ref; 321 using Ref = typename Traits::Ref;
317 using ConstRef = typename Traits::ConstRef; 322 using ConstRef = typename Traits::ConstRef;
318 using Helper = ArraySerializationHelper<T, IsUnionDataType<T>::value>; 323 using Helper = ArraySerializationHelper<T, IsUnionDataType<T>::value>;
319 using Element = T; 324 using Element = T;
320 325
321 // Returns null if |num_elements| or the corresponding storage size cannot be 326 // Returns null if |num_elements| or the corresponding storage size cannot be
322 // stored in uint32_t. 327 // stored in uint32_t.
323 static Array_Data<T>* New(size_t num_elements, Buffer* buf) { 328 static Array_Data<T>* New(size_t num_elements, Buffer* buf) {
324 if (num_elements > Traits::kMaxNumElements) 329 if (num_elements > Traits::kMaxNumElements)
325 return nullptr; 330 return nullptr;
326 331
327 uint32_t num_bytes = 332 uint32_t num_bytes =
328 Traits::GetStorageSize(static_cast<uint32_t>(num_elements)); 333 Traits::GetStorageSize(static_cast<uint32_t>(num_elements));
329 return new (buf->Allocate(num_bytes)) 334 return new (buf->Allocate(num_bytes))
330 Array_Data<T>(num_bytes, static_cast<uint32_t>(num_elements)); 335 Array_Data<T>(num_bytes, static_cast<uint32_t>(num_elements));
331 } 336 }
332 337
333 static bool Validate(const void* data, 338 static bool Validate(const void* data,
334 BoundsChecker* bounds_checker, 339 ValidationContext* validation_context,
335 const ContainerValidateParams* validate_params) { 340 const ContainerValidateParams* validate_params) {
336 if (!data) 341 if (!data)
337 return true; 342 return true;
338 if (!IsAligned(data)) { 343 if (!IsAligned(data)) {
339 ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT); 344 ReportValidationError(validation_context,
345 VALIDATION_ERROR_MISALIGNED_OBJECT);
340 return false; 346 return false;
341 } 347 }
342 if (!bounds_checker->IsValidRange(data, sizeof(ArrayHeader))) { 348 if (!validation_context->IsValidRange(data, sizeof(ArrayHeader))) {
343 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); 349 ReportValidationError(validation_context,
350 VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE);
344 return false; 351 return false;
345 } 352 }
346 const ArrayHeader* header = static_cast<const ArrayHeader*>(data); 353 const ArrayHeader* header = static_cast<const ArrayHeader*>(data);
347 if (header->num_elements > Traits::kMaxNumElements || 354 if (header->num_elements > Traits::kMaxNumElements ||
348 header->num_bytes < Traits::GetStorageSize(header->num_elements)) { 355 header->num_bytes < Traits::GetStorageSize(header->num_elements)) {
349 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER); 356 ReportValidationError(validation_context,
357 VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER);
350 return false; 358 return false;
351 } 359 }
352 if (validate_params->expected_num_elements != 0 && 360 if (validate_params->expected_num_elements != 0 &&
353 header->num_elements != validate_params->expected_num_elements) { 361 header->num_elements != validate_params->expected_num_elements) {
354 ReportValidationError( 362 ReportValidationError(
363 validation_context,
355 VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, 364 VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER,
356 MakeMessageWithExpectedArraySize( 365 MakeMessageWithExpectedArraySize(
357 "fixed-size array has wrong number of elements", 366 "fixed-size array has wrong number of elements",
358 header->num_elements, 367 header->num_elements,
359 validate_params->expected_num_elements).c_str()); 368 validate_params->expected_num_elements).c_str());
360 return false; 369 return false;
361 } 370 }
362 if (!bounds_checker->ClaimMemory(data, header->num_bytes)) { 371 if (!validation_context->ClaimMemory(data, header->num_bytes)) {
363 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); 372 ReportValidationError(validation_context,
373 VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE);
364 return false; 374 return false;
365 } 375 }
366 376
367 const Array_Data<T>* object = static_cast<const Array_Data<T>*>(data); 377 const Array_Data<T>* object = static_cast<const Array_Data<T>*>(data);
368 return Helper::ValidateElements(&object->header_, object->storage(), 378 return Helper::ValidateElements(&object->header_, object->storage(),
369 bounds_checker, validate_params); 379 validation_context, validate_params);
370 } 380 }
371 381
372 size_t size() const { return header_.num_elements; } 382 size_t size() const { return header_.num_elements; }
373 383
374 Ref at(size_t offset) { 384 Ref at(size_t offset) {
375 DCHECK(offset < static_cast<size_t>(header_.num_elements)); 385 DCHECK(offset < static_cast<size_t>(header_.num_elements));
376 return Traits::ToRef(storage(), offset); 386 return Traits::ToRef(storage(), offset);
377 } 387 }
378 388
379 ConstRef at(size_t offset) const { 389 ConstRef at(size_t offset) const {
(...skipping 27 matching lines...) Expand all
407 }; 417 };
408 static_assert(sizeof(Array_Data<char>) == 8, "Bad sizeof(Array_Data)"); 418 static_assert(sizeof(Array_Data<char>) == 8, "Bad sizeof(Array_Data)");
409 419
410 // UTF-8 encoded 420 // UTF-8 encoded
411 using String_Data = Array_Data<char>; 421 using String_Data = Array_Data<char>;
412 422
413 } // namespace internal 423 } // namespace internal
414 } // namespace mojo 424 } // namespace mojo
415 425
416 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_ 426 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_ARRAY_INTERNAL_H_
OLDNEW
« no previous file with comments | « mojo/public/cpp/bindings/BUILD.gn ('k') | mojo/public/cpp/bindings/lib/binding_state.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698