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 "base/callback.h" 9 #include "base/component_export.h" 10 #include "base/logging.h" 11 #include "base/macros.h" 12 #include "mojo/public/cpp/bindings/lib/validation_context.h" 13 14 namespace mojo { 15 16 class Message; 17 18 namespace internal { 19 20 enum ValidationError { 21 // There is no validation error. 22 VALIDATION_ERROR_NONE, 23 // An object (struct or array) is not 8-byte aligned. 24 VALIDATION_ERROR_MISALIGNED_OBJECT, 25 // An object is not contained inside the message data, or it overlaps other 26 // objects. 27 VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE, 28 // A struct header doesn't make sense, for example: 29 // - |num_bytes| is smaller than the size of the struct header. 30 // - |num_bytes| and |version| don't match. 31 // TODO(yzshen): Consider splitting it into two different error codes. Because 32 // the former indicates someone is misbehaving badly whereas the latter could 33 // be due to an inappropriately-modified .mojom file. 34 VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER, 35 // An array header doesn't make sense, for example: 36 // - |num_bytes| is smaller than the size of the header plus the size required 37 // to store |num_elements| elements. 38 // - For fixed-size arrays, |num_elements| is different than the specified 39 // size. 40 VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER, 41 // An encoded handle is illegal. 42 VALIDATION_ERROR_ILLEGAL_HANDLE, 43 // A non-nullable handle field is set to invalid handle. 44 VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE, 45 // An encoded pointer is illegal. 46 VALIDATION_ERROR_ILLEGAL_POINTER, 47 // A non-nullable pointer field is set to null. 48 VALIDATION_ERROR_UNEXPECTED_NULL_POINTER, 49 // An interface ID is illegal. 50 VALIDATION_ERROR_ILLEGAL_INTERFACE_ID, 51 // A non-nullable interface ID field is set to invalid. 52 VALIDATION_ERROR_UNEXPECTED_INVALID_INTERFACE_ID, 53 // |flags| in the message header is invalid. The flags are either 54 // inconsistent with one another, inconsistent with other parts of the 55 // message, or unexpected for the message receiver. For example the 56 // receiver is expecting a request message but the flags indicate that 57 // the message is a response message. 58 VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS, 59 // |flags| in the message header indicates that a request ID is required but 60 // there isn't one. 61 VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID, 62 // The |name| field in a message header contains an unexpected value. 63 VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD, 64 // Two parallel arrays which are supposed to represent a map have different 65 // lengths. 66 VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP, 67 // Attempted to deserialize a tagged union with an unknown tag. 68 VALIDATION_ERROR_UNKNOWN_UNION_TAG, 69 // A value of a non-extensible enum type is unknown. 70 VALIDATION_ERROR_UNKNOWN_ENUM_VALUE, 71 // Message deserialization failure, for example due to rejection by custom 72 // validation logic. 73 VALIDATION_ERROR_DESERIALIZATION_FAILED, 74 // The message contains a too deeply nested value, for example a recursively 75 // defined field which runtime value is too large. 76 VALIDATION_ERROR_MAX_RECURSION_DEPTH, 77 }; 78 79 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 80 const char* ValidationErrorToString(ValidationError error); 81 82 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 83 void ReportValidationError(ValidationContext* context, 84 ValidationError error, 85 const char* description = nullptr); 86 87 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 88 void ReportValidationErrorForMessage(mojo::Message* message, 89 ValidationError error, 90 const char* description = nullptr); 91 92 // This class may be used by tests to suppress validation error logging. This is 93 // not thread-safe and must only be instantiated on the main thread with no 94 // other threads using Mojo bindings at the time of construction or destruction. 95 class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 96 ScopedSuppressValidationErrorLoggingForTests { 97 public: 98 ScopedSuppressValidationErrorLoggingForTests(); 99 ~ScopedSuppressValidationErrorLoggingForTests(); 100 101 private: 102 const bool was_suppressed_; 103 104 DISALLOW_COPY_AND_ASSIGN(ScopedSuppressValidationErrorLoggingForTests); 105 }; 106 107 // Only used by validation tests and when there is only one thread doing message 108 // validation. 109 class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 110 ValidationErrorObserverForTesting { 111 public: 112 explicit ValidationErrorObserverForTesting(const base::Closure& callback); 113 ~ValidationErrorObserverForTesting(); 114 115 ValidationError last_error() const { return last_error_; } 116 void set_last_error(ValidationError error) { 117 last_error_ = error; 118 callback_.Run(); 119 } 120 121 private: 122 ValidationError last_error_; 123 base::Closure callback_; 124 125 DISALLOW_COPY_AND_ASSIGN(ValidationErrorObserverForTesting); 126 }; 127 128 // Used only by MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING. Don't use it directly. 129 // 130 // The function returns true if the error is recorded (by a 131 // SerializationWarningObserverForTesting object), false otherwise. 132 COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 133 bool ReportSerializationWarning(ValidationError error); 134 135 // Only used by serialization tests and when there is only one thread doing 136 // message serialization. 137 class COMPONENT_EXPORT(MOJO_CPP_BINDINGS_BASE) 138 SerializationWarningObserverForTesting { 139 public: 140 SerializationWarningObserverForTesting(); 141 ~SerializationWarningObserverForTesting(); 142 143 ValidationError last_warning() const { return last_warning_; } 144 void set_last_warning(ValidationError error) { last_warning_ = error; } 145 146 private: 147 ValidationError last_warning_; 148 149 DISALLOW_COPY_AND_ASSIGN(SerializationWarningObserverForTesting); 150 }; 151 152 } // namespace internal 153 } // namespace mojo 154 155 // In debug build, logs a serialization warning if |condition| evaluates to 156 // true: 157 // - if there is a SerializationWarningObserverForTesting object alive, 158 // records |error| in it; 159 // - otherwise, logs a fatal-level message. 160 // |error| is the validation error that will be triggered by the receiver 161 // of the serialzation result. 162 // 163 // In non-debug build, does nothing (not even compiling |condition|). 164 #define MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(condition, error, \ 165 description) \ 166 DLOG_IF(FATAL, (condition) && !ReportSerializationWarning(error)) \ 167 << "The outgoing message will trigger " \ 168 << ValidationErrorToString(error) << " at the receiving side (" \ 169 << description << ")."; 170 171 #endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_ERRORS_H_ 172