diff options
author | Janis Danisevskis <jdanis@google.com> | 2019-10-08 10:02:23 -0700 |
---|---|---|
committer | Janis Danisevskis <jdanis@google.com> | 2019-10-10 09:21:18 -0700 |
commit | cf5d7e83fd9d5e4303bc803bc3418429822c1f7d (patch) | |
tree | 99454857a931f709fdc04c5af0eab8a0b2dc2fed /keymaster | |
parent | c80550534460ded52ad4795db1923c2801d9080c (diff) | |
download | platform_hardware_interfaces-cf5d7e83fd9d5e4303bc803bc3418429822c1f7d.tar.gz platform_hardware_interfaces-cf5d7e83fd9d5e4303bc803bc3418429822c1f7d.tar.bz2 platform_hardware_interfaces-cf5d7e83fd9d5e4303bc803bc3418429822c1f7d.zip |
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
Diffstat (limited to 'keymaster')
-rw-r--r-- | keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h | 59 |
1 files changed, 35 insertions, 24 deletions
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<tag_type, tag> ttag, Args&&... args) */ template <typename ValueT> class NullOr { - template <typename T> - struct reference_initializer { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wnull-dereference" - static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); } -#pragma GCC diagnostic pop - }; - template <typename T> + using internal_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value, + std::remove_reference_t<ValueT>*, ValueT>; + struct pointer_initializer { - static T init() { return nullptr; } + static std::nullptr_t init() { return nullptr; } }; - template <typename T> 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<std::is_lvalue_reference<ValueT>::value || + std::is_pointer<ValueT>::value, + pointer_initializer, value_initializer>; + using deref_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value, reference_deref_t, + value_pointer_deref_t>; + + public: + NullOr() : value_(initializer_t::init()), null_(true) {} template <typename T> - using initializer_t = - std::conditional_t<std::is_lvalue_reference<T>::value, reference_initializer<T>, - std::conditional_t<std::is_pointer<T>::value, pointer_initializer<T>, - value_initializer<T>>>; - - public: - NullOr() : value_(initializer_t<ValueT>::init()), null_(true) {} - NullOr(ValueT&& value) : value_(std::forward<ValueT>(value)), null_(false) {} + NullOr(T&& value, typename std::enable_if< + !std::is_lvalue_reference<ValueT>::value && + std::is_same<std::decay_t<ValueT>, std::decay_t<T>>::value, + int>::type = 0) + : value_(std::forward<ValueT>(value)), null_(false) {} + template <typename T> + NullOr(T& value, typename std::enable_if< + std::is_lvalue_reference<ValueT>::value && + std::is_same<std::decay_t<ValueT>, std::decay_t<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_; }; |