summaryrefslogtreecommitdiffstats
path: root/keymaster
diff options
context:
space:
mode:
authorJanis Danisevskis <jdanis@google.com>2019-10-08 10:02:23 -0700
committerJanis Danisevskis <jdanis@google.com>2019-10-10 09:21:18 -0700
commitcf5d7e83fd9d5e4303bc803bc3418429822c1f7d (patch)
tree99454857a931f709fdc04c5af0eab8a0b2dc2fed /keymaster
parentc80550534460ded52ad4795db1923c2801d9080c (diff)
downloadplatform_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.h59
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_;
};