blob: da8fa3f67b99fe29167412de5504ff220a989423 [file] [log] [blame]
// 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 <sstream>
#include <string>
#include "mojo/public/cpp/environment/logging.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
namespace internal {
enum class ValidationError {
// There is no validation error.
NONE,
// An object (struct or array) is not 8-byte aligned.
MISALIGNED_OBJECT,
// An object is not contained inside the message data, or it overlaps other
// objects.
ILLEGAL_MEMORY_RANGE,
// A struct header doesn't make sense, for example:
// - |num_bytes| is smaller than the size of the struct header.
// - |num_bytes| and |version| don't match.
// TODO(yzshen): Consider splitting it into two different error codes. Because
// the former indicates someone is misbehaving badly whereas the latter could
// be due to an inappropriately-modified .mojom file.
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.
UNEXPECTED_ARRAY_HEADER,
// An encoded handle is illegal.
ILLEGAL_HANDLE,
// A non-nullable handle field is set to invalid handle.
UNEXPECTED_INVALID_HANDLE,
// An encoded pointer is illegal.
ILLEGAL_POINTER,
// A non-nullable pointer field is set to null.
UNEXPECTED_NULL_POINTER,
// |flags| in the message header is invalid. The flags are either
// inconsistent with one another, inconsistent with other parts of the
// message, or unexpected for the message receiver. For example the
// receiver is expecting a request message but the flags indicate that
// the message is a response message.
MESSAGE_HEADER_INVALID_FLAGS,
// |flags| in the message header indicates that a request ID is required but
// there isn't one.
MESSAGE_HEADER_MISSING_REQUEST_ID,
// The |name| field in a message header contains an unexpected value.
MESSAGE_HEADER_UNKNOWN_METHOD,
// Two parallel arrays which are supposed to represent a map have different
// lengths.
DIFFERENT_SIZED_ARRAYS_IN_MAP,
// A non-nullable union is set to null. (Has size 0)
UNEXPECTED_NULL_UNION,
};
const char* ValidationErrorToString(ValidationError error);
// TODO(vardhan): This can die, along with |ValidationErrorObserverForTesting|.
void ReportValidationError(ValidationError error,
std::string* 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);
};
// This takes in a string pointer, and provides a string stream which you can
// write to. On destruction, it sets the provided string to the contents of the
// string stream.
class ValidationErrorStringStream {
public:
explicit ValidationErrorStringStream(std::string* err_msg);
~ValidationErrorStringStream();
std::ostringstream& stream() { return stream_; }
private:
std::string* err_msg_;
std::ostringstream stream_;
MOJO_DISALLOW_COPY_AND_ASSIGN(ValidationErrorStringStream);
};
} // namespace internal
} // namespace mojo
// In a debug build, logs a serialization warning.
// TODO(vardhan): Make this work like an ostream.
#define MOJO_INTERNAL_DLOG_SERIALIZATION_WARNING(error, description) \
MOJO_DLOG(WARNING) << "The outgoing message will trigger " \
<< ValidationErrorToString(error) \
<< " at the receiving side (" << description << ")."
// In a debug build, this will use |ValidationErrorStringStream::stream()| and
// write to the supplied string if it is not null. In a non-debug + optimized
// build it should do nothing, while also discarding away operator<<() calls.
#ifdef NDEBUG
// The compiler will reduce the |true ? (void)0 : ...| expression to |(void)0|,
// thereby discarding the |ValidationErrorStringStream()| while still keeping
// this macro's use semantically valid.
#define MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err_msg) \
true ? (void)0 \
: ::mojo::internal::VoidifyOstream() & \
::mojo::internal::ValidationErrorStringStream(err_msg).stream()
#else
#define MOJO_INTERNAL_DEBUG_SET_ERROR_MSG(err_msg) \
::mojo::internal::ValidationErrorStringStream(err_msg).stream()
#endif // NDEBUG
#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_ERRORS_H_