From cf5d7e83fd9d5e4303bc803bc3418429822c1f7d Mon Sep 17 00:00:00 2001 From: Janis Danisevskis Date: Tue, 8 Oct 2019 10:02:23 -0700 Subject: Fix UB in class NullOr NullOr now stores the references a pointers internally. This fixes UB where the internal reference was initalized by dereferencing nullptr. Test: Compiles Bug: 121390225 Change-Id: I2073e5aeac401309aa63b08e05db3c467fab6b69 --- .../support/include/keymasterV4_0/keymaster_tags.h | 59 +++++++++++++--------- 1 file changed, 35 insertions(+), 24 deletions(-) (limited to 'keymaster') diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h index 97dab68217..cb29c64b1e 100644 --- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h +++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h @@ -280,39 +280,50 @@ inline KeyParameter Authorization(TypedTag ttag, Args&&... args) */ template class NullOr { - template - struct reference_initializer { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wnull-dereference" - static T&& init() { return *static_cast*>(nullptr); } -#pragma GCC diagnostic pop - }; - template + using internal_t = std::conditional_t::value, + std::remove_reference_t*, ValueT>; + struct pointer_initializer { - static T init() { return nullptr; } + static std::nullptr_t init() { return nullptr; } }; - template struct value_initializer { - static T init() { return T(); } + static ValueT init() { return ValueT(); } }; + struct value_pointer_deref_t { + static ValueT& deref(ValueT& v) { return v; } + }; + struct reference_deref_t { + static auto& deref(internal_t v) { return *v; } + }; + using initializer_t = std::conditional_t::value || + std::is_pointer::value, + pointer_initializer, value_initializer>; + using deref_t = std::conditional_t::value, reference_deref_t, + value_pointer_deref_t>; + + public: + NullOr() : value_(initializer_t::init()), null_(true) {} template - using initializer_t = - std::conditional_t::value, reference_initializer, - std::conditional_t::value, pointer_initializer, - value_initializer>>; - - public: - NullOr() : value_(initializer_t::init()), null_(true) {} - NullOr(ValueT&& value) : value_(std::forward(value)), null_(false) {} + NullOr(T&& value, typename std::enable_if< + !std::is_lvalue_reference::value && + std::is_same, std::decay_t>::value, + int>::type = 0) + : value_(std::forward(value)), null_(false) {} + template + NullOr(T& value, typename std::enable_if< + std::is_lvalue_reference::value && + std::is_same, std::decay_t>::value, + int>::type = 0) + : value_(&value), null_(false) {} bool isOk() const { return !null_; } - const ValueT& value() const & { return value_; } - ValueT& value() & { return value_; } - ValueT&& value() && { return std::move(value_); } + const ValueT& value() const& { return deref_t::deref(value_); } + ValueT& value() & { return deref_t::deref(value_); } + ValueT&& value() && { return std::move(deref_t::deref(value_)); } - private: - ValueT value_; + private: + internal_t value_; bool null_; }; -- cgit v1.2.3