1// Copyright 2014 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_ERRORS_H_
6#define MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_ERRORS_H_
7
8#include "mojo/public/cpp/system/macros.h"
9
10namespace mojo {
11namespace internal {
12
13enum ValidationError {
14  // There is no validation error.
15  VALIDATION_ERROR_NONE,
16  // An object (struct or array) is not 8-byte aligned.
17  VALIDATION_ERROR_MISALIGNED_OBJECT,
18  // An object is not contained inside the message data, or it overlaps other
19  // objects.
20  VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE,
21  // A struct header doesn't make sense, for example:
22  // - |num_bytes| is smaller than the size of the oldest version that we
23  // support.
24  // - |num_fields| is smaller than the field number of the oldest version that
25  // we support.
26  // - |num_bytes| and |num_fields| don't match.
27  VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER,
28  // An array header doesn't make sense, for example:
29  // - |num_bytes| is smaller than the size of the header plus the size required
30  // to store |num_elements| elements.
31  // - For fixed-size arrays, |num_elements| is different than the specified
32  // size.
33  VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER,
34  // An encoded handle is illegal.
35  VALIDATION_ERROR_ILLEGAL_HANDLE,
36  // A non-nullable handle field is set to invalid handle.
37  VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
38  // An encoded pointer is illegal.
39  VALIDATION_ERROR_ILLEGAL_POINTER,
40  // A non-nullable pointer field is set to null.
41  VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
42  // |flags| in the message header is an invalid flag combination.
43  VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION,
44  // |flags| in the message header indicates that a request ID is required but
45  // there isn't one.
46  VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID,
47};
48
49const char* ValidationErrorToString(ValidationError error);
50
51void ReportValidationError(ValidationError error,
52                           const char* description = NULL);
53
54// Only used by validation tests and when there is only one thread doing message
55// validation.
56class ValidationErrorObserverForTesting {
57 public:
58  ValidationErrorObserverForTesting();
59  ~ValidationErrorObserverForTesting();
60
61  ValidationError last_error() const { return last_error_; }
62  void set_last_error(ValidationError error) { last_error_ = error; }
63
64 private:
65  ValidationError last_error_;
66
67  MOJO_DISALLOW_COPY_AND_ASSIGN(ValidationErrorObserverForTesting);
68};
69
70// Used only by MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING. Don't use it directly.
71//
72// The function returns true if the error is recorded (by a
73// SerializationWarningObserverForTesting object), false otherwise.
74bool ReportSerializationWarning(ValidationError error);
75
76// Only used by serialization tests and when there is only one thread doing
77// message serialization.
78class SerializationWarningObserverForTesting {
79 public:
80  SerializationWarningObserverForTesting();
81  ~SerializationWarningObserverForTesting();
82
83  ValidationError last_warning() const { return last_warning_; }
84  void set_last_warning(ValidationError error) { last_warning_ = error; }
85
86 private:
87  ValidationError last_warning_;
88
89  MOJO_DISALLOW_COPY_AND_ASSIGN(SerializationWarningObserverForTesting);
90};
91
92}  // namespace internal
93}  // namespace mojo
94
95// In debug build, logs a serialization warning if |condition| evaluates to
96// true:
97//   - if there is a SerializationWarningObserverForTesting object alive,
98//     records |error| in it;
99//   - otherwise, logs a fatal-level message.
100// |error| is the validation error that will be triggered by the receiver
101// of the serialzation result.
102//
103// In non-debug build, does nothing (not even compiling |condition|).
104#define MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING( \
105    condition, error, description) \
106  MOJO_DLOG_IF(FATAL, (condition) && !ReportSerializationWarning(error)) \
107      << "The outgoing message will trigger " \
108      << ValidationErrorToString(error) << " at the receiving side (" \
109      << description << ").";
110
111#endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_ERRORS_H_
112