Home | History | Annotate | Download | only in lib
      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