• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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