From bfad7870167d3f3712c8a8af1cd294baae2f51ca Mon Sep 17 00:00:00 2001 From: Grace Cham Date: Tue, 16 Jul 2024 23:17:37 +0000 Subject: [PATCH] v5: Crash when dereferencing nullopt for std::optional Original author hscham . TODO(b/192529039): this is a temporary patch to address security concerns when migrating base:Optional and absl::optional to std::optional. libcxx upstream is working on decoupling hardening and debugging asserts and this patch should be replaced by the upstream patch upon completion. Change-Id: I3324856fff67b0109471bdf44f46bccd773407c2 --- libcxx/include/optional | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/libcxx/include/optional b/libcxx/include/optional index 41d7515a2b68..8484666fb11c 100644 --- a/libcxx/include/optional +++ b/libcxx/include/optional @@ -177,6 +177,8 @@ namespace std { */ +#include + #include <__assert> #include <__compare/compare_three_way_result.h> #include <__compare/three_way_comparable.h> @@ -786,33 +788,57 @@ public: } } - _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t operator->() const noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr add_pointer_t operator->() const noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value"); + if (!this->has_value()) { + fprintf(stderr, "optional operator-> called on a disengaged value\n"); + __builtin_trap(); + } return std::addressof(this->__get()); } - _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t operator->() noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr add_pointer_t operator->() noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value"); + if (!this->has_value()) { + fprintf(stderr, "optional operator-> called on a disengaged value\n"); + __builtin_trap(); + } return std::addressof(this->__get()); } - _LIBCPP_HIDE_FROM_ABI constexpr const value_type& operator*() const& noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr const value_type& operator*() const& noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); + if (!this->has_value()) { + fprintf(stderr, "optional operator-> called on a disengaged value\n"); + __builtin_trap(); + } return this->__get(); } - _LIBCPP_HIDE_FROM_ABI constexpr value_type& operator*() & noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type& operator*() & noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); + if (!this->has_value()) { + fprintf(stderr, "optional operator-> called on a disengaged value\n"); + __builtin_trap(); + } return this->__get(); } - _LIBCPP_HIDE_FROM_ABI constexpr value_type&& operator*() && noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr value_type&& operator*() && noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); + if (!this->has_value()) { + fprintf(stderr, "optional operator-> called on a disengaged value\n"); + __builtin_trap(); + } return std::move(this->__get()); } - _LIBCPP_HIDE_FROM_ABI constexpr const value_type&& operator*() const&& noexcept { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS constexpr const value_type&& operator*() const&& noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value"); + if (!this->has_value()) { + fprintf(stderr, "optional operator-> called on a disengaged value\n"); + __builtin_trap(); + } return std::move(this->__get()); } -- 2.46.0.792.g87dc391469-goog