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/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 
     85   ValidationError last_error() const { return last_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 
    111   ValidationError last_warning() const { return last_warning_; }
    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