summaryrefslogtreecommitdiffstats
path: root/mojo/public/cpp/bindings/lib/validation_errors.h
blob: 2abb1b7545620b73f55d6f6aa10e6ea19f74a3cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_ERRORS_H_
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_ERRORS_H_

#include "mojo/public/cpp/system/macros.h"

namespace mojo {
namespace internal {

enum ValidationError {
  // There is no validation error.
  VALIDATION_ERROR_NONE,
  // An object (struct or array) is not 8-byte aligned.
  VALIDATION_ERROR_MISALIGNED_OBJECT,
  // An object is not contained inside the message data, or it overlaps other
  // objects.
  VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE,
  // A struct header doesn't make sense, for example:
  // - |num_bytes| is smaller than the size of the oldest version that we
  // support.
  // - |num_fields| is smaller than the field number of the oldest version that
  // we support.
  // - |num_bytes| and |num_fields| don't match.
  VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER,
  // An array header doesn't make sense, for example:
  // - |num_bytes| is smaller than the size of the header plus the size required
  // to store |num_elements| elements.
  // - For fixed-size arrays, |num_elements| is different than the specified
  // size.
  VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER,
  // An encoded handle is illegal.
  VALIDATION_ERROR_ILLEGAL_HANDLE,
  // A non-nullable handle field is set to invalid handle.
  VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE,
  // An encoded pointer is illegal.
  VALIDATION_ERROR_ILLEGAL_POINTER,
  // A non-nullable pointer field is set to null.
  VALIDATION_ERROR_UNEXPECTED_NULL_POINTER,
  // |flags| in the message header is an invalid flag combination.
  VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION,
  // |flags| in the message header indicates that a request ID is required but
  // there isn't one.
  VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID,
  // Two parallel arrays which are supposed to represent a map have different
  // lengths.
  VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP
};

const char* ValidationErrorToString(ValidationError error);

void ReportValidationError(ValidationError error,
                           const char* description = nullptr);

// Only used by validation tests and when there is only one thread doing message
// validation.
class ValidationErrorObserverForTesting {
 public:
  ValidationErrorObserverForTesting();
  ~ValidationErrorObserverForTesting();

  ValidationError last_error() const { return last_error_; }
  void set_last_error(ValidationError error) { last_error_ = error; }

 private:
  ValidationError last_error_;

  MOJO_DISALLOW_COPY_AND_ASSIGN(ValidationErrorObserverForTesting);
};

// Used only by MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING. Don't use it directly.
//
// The function returns true if the error is recorded (by a
// SerializationWarningObserverForTesting object), false otherwise.
bool ReportSerializationWarning(ValidationError error);

// Only used by serialization tests and when there is only one thread doing
// message serialization.
class SerializationWarningObserverForTesting {
 public:
  SerializationWarningObserverForTesting();
  ~SerializationWarningObserverForTesting();

  ValidationError last_warning() const { return last_warning_; }
  void set_last_warning(ValidationError error) { last_warning_ = error; }

 private:
  ValidationError last_warning_;

  MOJO_DISALLOW_COPY_AND_ASSIGN(SerializationWarningObserverForTesting);
};

}  // namespace internal
}  // namespace mojo

// In debug build, logs a serialization warning if |condition| evaluates to
// true:
//   - if there is a SerializationWarningObserverForTesting object alive,
//     records |error| in it;
//   - otherwise, logs a fatal-level message.
// |error| is the validation error that will be triggered by the receiver
// of the serialzation result.
//
// In non-debug build, does nothing (not even compiling |condition|).
#define MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(                        \
    condition, error, description)                                       \
  MOJO_DLOG_IF(FATAL, (condition) && !ReportSerializationWarning(error)) \
      << "The outgoing message will trigger "                            \
      << ValidationErrorToString(error) << " at the receiving side ("    \
      << description << ").";

#endif  // MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_ERRORS_H_