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